当前位置:  开发笔记 > 编程语言 > 正文

什么案例需要Java中的同步方法访问?

如何解决《什么案例需要Java中的同步方法访问?》经验,为你挑选了2个好方法。

在什么情况下需要同步访问实例成员?我理解,对类的静态成员的访问总是需要同步 - 因为它们在类的所有对象实例之间共享.

我的问题是,如果我不同步实例成员,我什么时候会不正确?

例如,如果我的班级是

public class MyClass {
    private int instanceVar = 0;

    public setInstanceVar()
    {
        instanceVar++;
    }

    public getInstanceVar()
    {
        return instanceVar;
    }
}

在什么情况下(使用类MyClass)我需要有方法: public synchronized setInstanceVar()public synchronized getInstanceVar()

提前感谢您的回答.



1> Daniel Spiew..:

synchronized修饰符实在是一个糟糕的主意,应该不惜一切代价避免.我认为值得称道的是,Sun试图让锁定更容易实现,但synchronized只会造成比它值得更多的麻烦.

问题是,synchronized方法实际上只是用于获取锁定this并在方法持续时间内持有它的语法糖.因此,public synchronized void setInstanceVar()相当于这样的事情:

public void setInstanceVar() {
    synchronized(this) {
        instanceVar++;
    }
}

这有两个原因:

synchronized同一类中的所有方法都使用完全相同的锁,这会降低吞吐量

任何人都可以访问锁,包括其他类的成员.

没有什么可以阻止我在另一个类中做这样的事情:

MyClass c = new MyClass();
synchronized(c) {
    ...
}

在该synchronized块中,我持有所有synchronized方法所需的锁MyClass.这进一步降低了吞吐量并大大增加了死锁的可能性.

更好的方法是拥有一个专用lock对象并synchronized(...)直接使用该块:

public class MyClass {
    private int instanceVar;
    private final Object lock = new Object();     // must be final!

    public void setInstanceVar() {
        synchronized(lock) {
            instanceVar++;
        }
    }
}

或者,您可以使用java.util.concurrent.Lock接口和java.util.concurrent.locks.ReentrantLock实现来实现基本相同的结果(事实上,它在Java 6上是相同的).


"lock"不需要"静态",因为它正在同步的数据(`instanceVar`)本身不是静态的.静态锁几乎总是一个非常非常严重的问题的迹象,你应该尽可能避免它们.

2> Jon Skeet..:

这取决于您是否希望您的类是线程安全的.大多数类不应该是线程安全的(为简单起见),在这种情况下,您不需要同步.如果您需要它是线程安全的,您应该同步访问使变量volatile.(它避免了其他线程获得"陈旧"数据.)

推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有