JAVA多线程使用静态对象作锁出现的问题

qq_34406574 2017-05-25 01:26:35
我的代码是这样的:

public class ThreadLockTest2 implements Runnable{
private static Integer count = 0;
@Override
public void run() {
synchronized(count){
for(int i = 0 ; i < 5 ; i ++){
System.out.println(Thread.currentThread().getName()+"> "+count++);
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new ThreadLockTest2(),"th1");
Thread t2 = new Thread(new ThreadLockTest2(),"th2");
t1.start();
t2.start();
}
}

反复运行之后,出现这样的结果

th1> 0
th2> 1
th2> 2
th2> 3
th2> 4
th2> 5
th1> 5
th1> 6
th1> 7
th1> 8

按道理来讲,使用静态对象作锁不是能够宝成线程间所有对象同步吗,有没有大神能够解答
...全文
398 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
a350062174 2017-06-03
  • 打赏
  • 举报
回复
引用 6 楼 qq_34406574 的回复:
[quote=引用 2楼a350062174 的回复:]

    public static void main(String[] args) {
        Integer i=0;
        Integer i2 = i;
        Integer i3=i++;
        System.out.println(i==i2);//false
        System.out.println(i==i3);//false
        System.out.println(i2==i3);//true
    }
++ 运算符会将count 对象重新赋值. 执行++ 后的count 对象和之前会不一样. synchronized(count) 这里两个线程锁的不是同一对象,才出现楼主的现象. synchronized 你用 不可变对象.(ThreadLockTest2.class) 比较好
请问一下 Integer i = 0; Integer i2 = i; 这里的i2是i的一个引用还是新的一个对象,按你的回答i2和i属于不同的对象,但是这里确实没有为i2分配空间。谢谢大神[/quote] 执行 Integer i2 = i;之后 i2 和i 指向同一个对象. 但在执行 Integer i3=i++; 之后 i又分配了一个新的对象,而i2不变, 所以i2 和i不同.

        Integer i=0;
        Integer i2 = i;
        System.out.println(i==i2);//true
        Integer i3=i++;
        System.out.println(i==i2);//false
        System.out.println(i==i3);//false
        System.out.println(i2==i3);//true

qq_34406574 2017-05-27
  • 打赏
  • 举报
回复
引用 2楼a350062174 的回复:

    public static void main(String[] args) {
        Integer i=0;
        Integer i2 = i;
        Integer i3=i++;
        System.out.println(i==i2);//false
        System.out.println(i==i3);//false
        System.out.println(i2==i3);//true
    }
++ 运算符会将count 对象重新赋值. 执行++ 后的count 对象和之前会不一样. synchronized(count) 这里两个线程锁的不是同一对象,才出现楼主的现象. synchronized 你用 不可变对象.(ThreadLockTest2.class) 比较好
请问一下 Integer i = 0; Integer i2 = i; 这里的i2是i的一个引用还是新的一个对象,按你的回答i2和i属于不同的对象,但是这里确实没有为i2分配空间。谢谢大神
Jcon_ 2017-05-25
  • 打赏
  • 举报
回复
可以这样锁
public class ThreadLockTest2 implements Runnable{
    private static Integer count = 0;
    @Override
    public void run() {
        synchronized(this){
            for(int i = 0 ; i < 5 ; i ++){
                System.out.println(Thread.currentThread().getName()+"> "+count++);
            }
        }
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(new ThreadLockTest2(),"th1");
        Thread t2 = new Thread(new ThreadLockTest2(),"th2");
        t1.start();
        t2.start();
    }
}
爱摸鱼de老邪 2017-05-25
  • 打赏
  • 举报
回复
操作count++的结果会改变变量count的引用,所以同步块synchronized (count)锁定的是不同的实例,也就是没有起到锁的作用。
a350062174 2017-05-25
  • 打赏
  • 举报
回复

    public static void main(String[] args) {
        Integer i=0;
        Integer i2 = i;
        Integer i3=i++;
        System.out.println(i==i2);//false
        System.out.println(i==i3);//false
        System.out.println(i2==i3);//true
    }
++ 运算符会将count 对象重新赋值. 执行++ 后的count 对象和之前会不一样. synchronized(count) 这里两个线程锁的不是同一对象,才出现楼主的现象. synchronized 你用 不可变对象.(ThreadLockTest2.class) 比较好
  • 打赏
  • 举报
回复
count++之后,对象就变了,可以这么写

public class ThreadLockTest2 implements Runnable{
    private static Integer count = 0;
    private static Object lockObject = new Object();
    public void run() {
        synchronized(lockObject){
            for(int i = 0 ; i < 5 ; i ++){
                System.out.println(Thread.currentThread().getName()+"> "+ count++);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(new ThreadLockTest2(),"th1");
        Thread t2 = new Thread(new ThreadLockTest2(),"th2");
        t1.start();
        t2.start();
    }
}
lvdaan 2017-05-25
  • 打赏
  • 举报
回复
同步锁必须是对象,不变的。 一般的,我们把当前并发访问的共同资源作为同步监听对象。 上面的几个例子都可以

62,626

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧