iteye_7931 2011-11-03 10:37
浏览 228
已采纳

关于线程同步synchronized的一个基础问题

代码如下:
class Counter {
private static int count;

//Object lock = new Object();

public  int getCount() {
    synchronized(Counter.class){
        return count++;
    }

// synchronized(lock){
// return count++;
// }

}

}

这个类用来生成序列号,测试发现:
如果在 getCount方法上面用同步 public [color=red]synchronized[/color] int getCount() {...}当并发调用线程很多时,返回的序列号仍然会有重复。
如果自定义一个对象,在这个对象上应用同步,也会出现序列号重复问题。
只有对 Counter.class 加锁才能够达到预期的效果。

这三种方式有啥区别,线程的那些书上面的例子不都是在方法上面直接用同步么?请各位帮忙解答。

  • 写回答

5条回答 默认 最新

  • mingyang2013 2011-11-04 23:34
    关注

    楼主,我完全理解你的意思!你一定看楼上的回复看得晕了吧?那么,我会以简单易懂的语言来回答这个问题,请往下看:

    1、你总共用了三种加锁的方法:
    (1)
    [code="java"]
    public int getCount() {
    synchronized(Counter.class){
    return count++;
    }
    [/code]
    (2)
    [code="java"]synchronized(lock){
    return count++;
    } [/code]
    (3)
    [code="java"]public synchronized int getCount() {...}[/code]

    2、其实,你的第(3)种方法和如下方式是等同的:
    [code="java"]
    public int getCount() {
    synchronized(this){
    return count++;
    }
    [/code]

    3、那么,你需要明白java的加锁机制是怎样的。即,多个线程执行一段代码,只有拿到这段代码的锁之后才能执行,其他线程如果拿不到这个“锁”则只能等待,这叫做“互斥”。而要确保线程与线程之间的互斥,只有当他们去拿锁时,那个锁是同一个对象!(这点理解到很重要,是同一对象!)。

    4、好了,看了上面我的说明,这下你能明白错误发生原因了。
    A. 在你的第(1)种加锁方式中,用的是Counter.class,这是类的元对象,在整个虚拟机运行过程中可以认为是唯一的,他是在类被加载的时候创建的(这个稍微扯得有点远,你明白他是唯一的一个对象就ok了),所以不同线程执行里面的代码时,它们是去拿的同一把锁,也就能保证互斥了。
    B. 方式(2)加锁中,很明显,不同线程中,你会new不同的Counter,那么,作为“锁”的对象lock也就不是同一个,也就无法保证互斥。
    C. 方式(3)相信你应该能理解了吧,你在不同线程中用new的不同Counter调用方法,this肯定也就不同了。

    5、ok,希望你看懂了我的说明,我可是手敲的这么字啊。呵呵,如有不懂之处,可以给我私信哈。我当时学多线程时也是相当痛苦,不过理解了就发现也不是那么痛苦了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)