首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无竞争条件:两个具有不同锁但共享数据的块

无竞争条件:两个具有不同锁但共享数据的块
EN

Stack Overflow用户
提问于 2018-10-09 08:07:49
回答 2查看 80关注 0票数 4

我有两个线程thread_1和thread_2在同一个对象unsafeObj上调用不同的方法。

  • thread_1调用unsafeObj.incrementVAR_v1() 10次
  • thread_2调用unsafeObj.incrementVAR_v2() 10次

这两个实例方法都有一个具有不同锁的synchronized-block (LOCK_1和LOCK_2) 访问相同的实例字段VAR

代码语言:javascript
复制
public void icrementVAR_v1() {
  synchronized(LOCK_1) {
    ++VAR;
    print("Thread 1: "  + VAR)
  }
}

public void incrementVAR_v2() {
  synchronized(LOCK_2) {
    ++VAR;
    print("Thread 2: " + VAR);
  }
}

考虑到这两个synchronized-blocks使用不同的锁,我本来预计VAR会被并发访问,从而导致更新丢失(VAR小于20)。但这不是我所观察到的。有人能给我解释一下为什么不是这样吗?

示例输出:

代码语言:javascript
复制
Thread 2: 2
Thread 1: 1
Thread 2: 3
Thread 1: 4
Thread 2: 5
Thread 1: 6
Thread 2: 7
Thread 1: 8
Thread 2: 9
Thread 1: 10
Thread 2: 11
Thread 1: 12
Thread 2: 13
Thread 1: 14
Thread 2: 15
Thread 1: 16
Thread 2: 17
Thread 1: 18
Thread 2: 19
Thread 1: 20
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-09 09:04:32

正如我所预期的那样,对字段的并发访问(由于有两个不同的锁),VAR 确实会导致一个争用条件,但是为了观察它,需要大量的迭代(在我的例子中,每个线程中有100'000次迭代)。汲取的经验教训:

  • ☝种族条件很难复制
  • 在尝试复制它们时使用大量的迭代。
票数 1
EN

Stack Overflow用户

发布于 2018-10-09 09:24:34

只是为了好玩,在10岁(当然,它没有保证)

代码语言:javascript
复制
public class Main {

    public static void main(String[] args) {
        Thread t1=new Thread(()->{
            for(int i=0;i<10;i++){
                icrementVAR_v1();

            }
        }
        );
        Thread t2=new Thread(()->{
            for(int i=0;i<10;i++){
                incrementVAR_v2();

            }
        }
        );
        t1.start();
        t2.start();
    }
    static Object LOCK_1=new Object();
    static Object LOCK_2=new Object();
    static int VAR=0;
    public static void icrementVAR_v1() {
        synchronized(LOCK_1) {
            ++VAR;
            Thread.yield();
            System.out.println("Thread 1: "  + VAR);
        }
    }

    public static void incrementVAR_v2() {
        synchronized(LOCK_2) {
            ++VAR;
            Thread.yield();
            System.out.println("Thread 2: " + VAR);
        }
    }
    public static void print(String s){
        System.out.println(s);
    }

}

示例输出:

代码语言:javascript
复制
Thread 1: 2
Thread 2: 2
Thread 1: 4
Thread 2: 5
Thread 1: 6
Thread 2: 7
Thread 1: 8
Thread 2: 9
Thread 1: 10
Thread 1: 11
Thread 2: 12
Thread 1: 13
Thread 2: 14
Thread 1: 15
Thread 2: 16
Thread 1: 17
Thread 2: 18
Thread 1: 19
Thread 2: 19
Thread 2: 20
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52716190

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档