繁体   English   中英

Java线程安全计数器自己的锁实现

[英]Java thread safe counter own lock implementation

我只是想过如何在从不同线程修改变量时锁定诸如int之类的变量。 我不会以这种方式使用它,而且我了解Java中的synced关键字,但是我想了解这一点以及它一般如何工作。

这就是我的代码:

private int i = 0;
private int lock = 0;

public void count(int lock) {
    while (true) {
        if (this.lock == 0) {
            this.lock = lock;
        }

        if (this.lock == lock) {
            i ++;
            this.lock = 0;
            return;
        }
    }
}

问题:行得通吗? 这个计数器线程安全吗? 如果是,则:synced关键字是否是类似的工作? 如果否:为什么不呢?

编辑:我忘了提到每个线程使用不同的锁值调用count方法。

简短的答案是,“不”不能保证那里的线程安全。

更长的答案是您需要查看Java内存模型以了解原因。 问题的部分原因是不同的线程可能无法同时看到更改。 内存模型仅保证写后的读取在执行写操作的同一线程中看到更新的值,除非跨越了内存屏障。 另一个线程即使在另一个线程执行了写操作之后执行了读取操作,也可能看不到该更新。 除非您使用volatile关键字描述变量。 或使用synchronized关键字来确保只有一个线程在更新该值。 这种行为使Java运行时可以优化代码,可能是通过在循环中内联它注意到的东西来保持不变,并且还可以使用本机汇编语言,该语言提供同步保证,但可以证明更快。

问题的另一部分是,当两个更新同时发生在不同线程上时,确保对两个线程可用相同结果的唯一方法是使用相应的低级汇编语言指令-这可能是称为compareAndSet,compareAndSwap或testAndSet。

因此,去编写您编写的代码,完全可以实现这种执行顺序的等效功能(其中T1和T2为单独的线程)...

// assuming i begins at 0.
T1: if this.lock == true
T2: if this.lock == true
T1: this.lock = lock
T1: if this.lock == lock     // evaluates to true
T2: if this.lock == lock     // evaluates to true
T1: this.lock = lock
T2: this.lock = lock

实际上,它更加复杂,因为您不能说每个指令都是CPU上的单个指令。 从根本上讲,您可以让两个线程同时执行某种更新,所有伴随的结果都是两次更新或丢失。

甚至更简单的答案:将java.util.concurrent提供的Atomic原语用于线程安全计数器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM