Java 同步方法不作为锁工作??为什么不锁定计数

Java 同步方法不作为锁工作??为什么不锁定计数,java,multithreading,thread-safety,locking,synchronize,Java,Multithreading,Thread Safety,Locking,Synchronize,如下面代码所示,我对我的count变量使用了强化锁(监视器),通过将synchIncrement()方法设置为同步方法,一次只能访问一个线程。那么O/P应该是20000,但仍然会出现一些时差值 为什么? 公共类SynchBlockThread{ 私有整数计数=0; 私有同步的void synchIncrement(){ 计数++; } 公共静态void main(字符串[]args){ SynchBlockThread sBT=新的SynchBlockThread(); sBT.doWork()

如下面代码所示,我对我的
count
变量使用了强化锁(监视器),通过将
synchIncrement()
方法设置为同步方法,一次只能访问一个
线程。那么O/P应该是
20000
,但仍然会出现一些时差值

为什么?

公共类SynchBlockThread{
私有整数计数=0;
私有同步的void synchIncrement(){
计数++;
}
公共静态void main(字符串[]args){
SynchBlockThread sBT=新的SynchBlockThread();
sBT.doWork();
}
私房{
线程t1=新线程(新的可运行线程(){
@凌驾
公开募捐{

对于(inti=0;i来说,这是一个很难发现的问题

doWork()
方法的末尾,您加入了
线程t1
两次,因此打印结果时
线程t2
仍在工作

要用代码表示它,请执行以下操作:

try {
    t1.join();
    t1.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
应该是

try {
    t1.join();
    t2.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}

同步方法的作用是正确的。问题是,您没有等待第二个
线程在第二个线程终止之前打印
计数
,因此您还应该添加
t2.join();

try {
    t1.join();
    t2.join();
} catch (InterruptedException e) { ... }

让我们考虑一下你的方法的一个更有趣的版本:

private void doWork() throws InterruptedException {
    final int n = 2;

    final CountDownLatch latch = new CountDownLatch(n);
    final ExecutorService service = Executors.newFixedThreadPool(n);
    final Runnable task = () -> {
        for (int i = 0; i < 10000; i++) {
            synchIncrement();
        }
        latch.countDown();
    };

    for (int i = 0; i < n; ++i) {
        service.execute(task);
    }

    latch.await();
    service.shutdown();
    System.out.println(count);
}
private void doWork()引发InterruptedException{
最终整数n=2;
最终倒计时闩锁=新倒计时闩锁(n);
final ExecutorService service=Executors.newFixedThreadPool(n);
最终可运行任务=()->{
对于(int i=0;i<10000;i++){
synchIncrement();
}
倒计时();
};
对于(int i=0;i

我引入了一个固定大小的
ExecutorService
来避免自己创建线程。我编写了一个
CountDownLatch
来知道所有任务何时完成执行,这样我就可以关闭服务并打印结果。

不需要提供整个屏幕的屏幕截图来证明您得到的值与不同de>20000
。默认情况下,我们相信您:)
private void doWork() throws InterruptedException {
    final int n = 2;

    final CountDownLatch latch = new CountDownLatch(n);
    final ExecutorService service = Executors.newFixedThreadPool(n);
    final Runnable task = () -> {
        for (int i = 0; i < 10000; i++) {
            synchIncrement();
        }
        latch.countDown();
    };

    for (int i = 0; i < n; ++i) {
        service.execute(task);
    }

    latch.await();
    service.shutdown();
    System.out.println(count);
}