You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无Object Locking实现代码块原子执行的多线程同步方案问询

Hey there! Let's figure out how to make those two print statements run atomically without relying on dummy synchronized objects or wait/notify. The core issue here is preventing other threads from interrupting the pair of println calls—so we need a way to guarantee those two lines execute back-to-back, no interruptions.

Solution 1: Synchronize on System.out itself

Since all your threads are using System.out to print, you can use this object as your lock. It’s a natural, existing object (no dummy required) and ensures only one thread can execute the block of print statements at a time. Here’s how to modify your code:

public class Main {
    public static void main(String[] args) {
        int sleepTime = 10, N = 1000;
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < N; i++) {
                synchronized (System.out) { // Lock on System.out directly
                    System.out.println("Thread one rules!!");
                    System.out.println("Im in 1!!!\n");
                }
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {}
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < N; i++) {
                synchronized (System.out) {
                    System.out.println("Thread two rules!!");
                    System.out.println("Im in 2!!!\n");
                }
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {}
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

This works because System.out is a shared object across all threads, so synchronizing on it ensures mutual exclusion for your print block. No dummy objects needed, and it’s straightforward.

Solution 2: Use ReentrantLock for more control

If you want a more flexible locking mechanism (great for scaling to hundreds of threads), use java.util.concurrent.locks.ReentrantLock. It’s more performant in high-concurrency scenarios and gives you explicit control over locking/unlocking:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    // Global lock instance shared by all threads
    private static final Lock printLock = new ReentrantLock();

    public static void main(String[] args) {
        int sleepTime = 10, N = 1000;
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < N; i++) {
                printLock.lock(); // Acquire the lock
                try {
                    // Critical section: these lines run atomically
                    System.out.println("Thread one rules!!");
                    System.out.println("Im in 1!!!\n");
                } finally {
                    printLock.unlock(); // Always release the lock, even if an exception occurs
                }
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {}
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < N; i++) {
                printLock.lock();
                try {
                    System.out.println("Thread two rules!!");
                    System.out.println("Im in 2!!!\n");
                } finally {
                    printLock.unlock();
                }
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {}
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

Why your mySocketServer approach caused timing issues

Using mySocketServer as a lock is risky because that object’s lock is likely being used by other parts of your application (like network I/O operations). This can lead to unexpected lock contention—your print threads might wait longer than necessary, or other critical operations on the socket server could be blocked, causing weird timing behavior. The solutions above use locks dedicated to the print atomicity requirement, so they don’t interfere with other business logic.

Both solutions work seamlessly with hundreds of threads: ReentrantLock is optimized for high concurrency, and even the System.out lock is sufficient since print operations are I/O-bound (the lock contention won’t be a bottleneck compared to the slow I/O itself).

内容的提问来源于stack exchange,提问作者MrRobot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:39:54