java 并发编程实践--客户端加锁机制。

发布于 2022-09-12 02:32:23 字数 657 浏览 20 评论 0

在看Java Concurrency programm in practice.的客户端编程时。指出同步需要注意是不是同一个锁。书上给出线程安全的方法。

程序清单4-15,P61

public class ListHelper<E> {
    public List<E> list = Collections.synchroinedList(new ArrayList<E>());
    
    public synchronized boolean putIfAbsent(E e) {
        boolean absent = !list.contains(e);
        if (absent) {
            list.add(e)
        }
        
        return absent;
 }

根据我的理解ListHelper的putIfAbsent方法的锁是加在其实例对象上。看了Collections源码,synchronizedList 使用的是同步块,是SynchronizedList 内部类的 final Object mutex 上,为什么是线程安全的?难道是,mutex 是其成员变量,所以会排斥使用成员变量的实现同步?。请给位大神解答, 谢谢。 可以讲一下原理吗?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ヤ经典坏疍 2022-09-19 02:32:23

Java中的任何对象都可以作为锁,这是 synchronized 锁机制的基础,有以下三种情况:

  1. 对于普通同步方法,锁是当前实例对象;
  2. 静态同步方法,锁是当前类的 Class 对象;
  3. 对于同步代码块,锁是 synchonized 括号里配置的对象。

你给出的ListHelper的例子是第一种情况,锁是ListHelper的实例对象,而SynchronizedList是第三种情况,锁是mutex变量,不管是哪种情况,线程都必须在获得锁之后才能继续执行,这就保证同一时刻只能有一个线程执行该操作,也就实现了线程安全。

淡看悲欢离合 2022-09-19 02:32:23

补充 2 这种情况,synchronized(class) 也是锁当前类 class

紫轩蝶泪 2022-09-19 02:32:23

我知道了,synchronizedList在构造器中将mutex = this.

耳钉梦 2022-09-19 02:32:23

由于list是一个public域,所以在执行putIfAbsent可以有别的线程操作list,并且putIfAbsent方法不是一个原子性操作,所以这不是一个线程安全的类型。

具体修改方法有:
1.私有化list域,这样对list进行操作的线程一定是当前putIfAbsent线程。
2.使用客户端加锁,对该方法和list使用相同的锁,由于synchronized(list)就是使用list的内部锁,所以可以实现只有一个线程能操作list。
3.修改putIfAbsent方法为原子操作,不满足题意故去除。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文