java - 具有静态属性的同步块(synchronized block) vs 共享属性 vs 同步方法

标签 java multithreading synchronization

我测试了同一个问题的三个版本,希望所有版本都能提供完美的同步:

1) 使用静态变量作为锁:

public class SynchronizedIncrement implements Runnable {
    private static int x = 0;
    private Object o = new Object();

    public void run() {
        for (int i=0; i<10000; ++i)
            synchronized(o) {
                ++x;
            }
    }
}

2) 使用与锁相同的对象,在构造函数中作为参数传递:

public class SynchronizedIncrement implements Runnable {
    private static int x = 0;
    private Object o = null;

    public SynchronizedIncrement(Object o) {
        this.o = o;
    }

    public void run() {
        for (int i=0; i<10000; ++i)
                synchronized(o) {
                    ++x;
                }
    }
}

3) 将run() 声明为同步 方法:

public synchronized void run() {
    for (int i=0; i<10000; ++i)
        ++x;
}

我正在使用 100 个线程的固定线程池进行测试:

public static void main(String[] args) {
    ExecutorService es = Executors.newFixedThreadPool(100);
    //Object obj = new Object(); // used as argument for the second version
    for (int i=0; i<100; ++i)
        es.submit(new Thread(new SynchronizedIncrement()));
    es.shutdown();
    while (!es.isTerminated());
    System.out.println(x);
}

版本 1、2 和 3 的输出:

560126
1000000
976082

只有第二个返回预期结果。为什么其他两个失败了?

最佳答案

  1. 第一个代码将使用引用 o 作为同步对象监视器。对象 o 对于 SynchronizedIncrement 的每个实例都是不同的对象,因此每个线程都会锁定自己的监视器,从而允许它们全部并行运行,从而不一致地递增静态变量 x。

  2. 第二个实现将使用作为参数传递给构造函数的对象来锁定线程。您有一个要传递给所有线程的引用 (obj),在这种情况下,所有同步都将在同一个对象上完成,从而使静态变量 x 持续递增。

  3. 最后一段代码将在“this”(本身)上同步,因此它的行为与第一个版本相同。

通常的设计,是将多线程访问的数据封装在不同的类中,并将接口(interface)方法同步到该类。

在这里,权衡是拥有一个方法 incX() 并声明:

static synchronized void incX(){
    x++;
}

在这种情况下,您的运行方法不需要同步。

关于java - 具有静态属性的同步块(synchronized block) vs 共享属性 vs 同步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24362284/

相关文章:

java - 我无法检索可用 cookie 的列表

python - 将 telethon 与 django : There is no current event loop in thread 'Thread-1' 一起使用

apache-kafka - 同步来自多个数据源的数据

java - Java 中的同步?

java - 使用线程计算查询的响应时间

java - 更改 Java 中的键盘输入语言

java - 回答 fileoutputstreams 中 java 中 I/O 流刷新的必要性

javax.script.ScriptException : sun. org.mozilla.javascript.internal.EcmaError:ReferenceError: "document"未定义

multithreading - 玩!框架 : Limit concurrent non-blocking IO calls made via WS

multithreading - vxworks 任务如何让所有其他较低优先级的任务在单个多任务循环中运行?