synchronized锁住对象时候两个线程却同时能访问的错误

sinat_30166251 2015-07-28 12:00:43
我在测试线程同步时候发现用synchronized关键字锁住对象时候另外的线程居然可以访问,然后我换成了Lock锁,就杜绝了这个问题,不知道是怎么回事,求大神路过回答我的困惑。

代码如下:

package com.java.test;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockTest {

private Integer count = 0;
private Lock lock = new ReentrantLock();

public Runnable run1 = new Runnable(){
@Override
public void run() {
// lock.lock();
synchronized(count) {
while(count < 1000) {
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " run1: "+count++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// lock.unlock();
}};

public Runnable run2 = new Runnable(){
@Override
public void run() {
// lock.lock();
synchronized(count) {
while(count < 1000) {
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " run2: "+count++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// lock.unlock();
}};

public Runnable run3 = new Runnable(){
@Override
public void run() {
// lock.lock();
synchronized(count) {
while(count < 1000) {
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " run3: "+count++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// lock.unlock();
}};

public Runnable run4 = new Runnable(){
@Override
public void run() {
// lock.lock();
synchronized(count) {
while(count < 1000) {
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " run4: "+count++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// lock.unlock();
}};

public static void main(String[] args) throws InterruptedException {
LockTest t = new LockTest();
new Thread(t.run1).start();
Thread.sleep(1000);
new Thread(t.run2).start();
Thread.sleep(1000);
new Thread(t.run3).start();
Thread.sleep(1000);
new Thread(t.run4).start();
}

}


程序使用synchronized关键字时的输出:
Thread-0 run1: 0
Thread-0 run1: 1
Thread-2 run3: 2
Thread-0 run1: 3
Thread-2 run3: 4
Thread-0 run1: 5
Thread-2 run3: 6

程序使用lock锁时达到了我的目的
Thread-0 run1: 0
Thread-0 run1: 1
Thread-0 run1: 2
Thread-0 run1: 3
Thread-0 run1: 4
Thread-0 run1: 5
Thread-0 run1: 6
不知道怎么回事。。。。
...全文
361 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
prideofme 2017-09-11
  • 打赏
  • 举报
回复
楼主有没有试一下AtomicInteger来count++?如果可以说明是count++,sleep的时候是不会释放锁的,这是只有持有相同锁的线程能够重入
util_00000 2015-07-28
  • 打赏
  • 举报
回复
synchronized关键字,,是同步机制的,,每个线程都有可能执行,但是每次对对象进行操作的,只有一个线程,所以并不是完全意义上的锁住。。lock 加锁 将 资源锁住,其他 需要该资源的线程 会处于就绪状态,这样就可以选择自己想释放锁的时候释放 。
nickycheng 2015-07-28
  • 打赏
  • 举报
回复
count++会导致count对象变为另一个新的Integer。不是同一个实例。
迷林 2015-07-28
  • 打赏
  • 举报
回复
我相信他们已经能解决你的问题了吧?楼主可以结贴了
gukuitian 2015-07-28
  • 打赏
  • 举报
回复
count=count+1也是和count++一样的,都是先调用Integer的intValue()取到基础类型的值,计算完成再封装成Integer, 就是说对像一直在变化; 你可以把count++语句去掉,再试一下
引用 2 楼 cricel 的回复:
楼上说的使用count++会导致count对象编程另外一个新的integer。不是一个实例,但是我试了一下如果我把count++改成count=count+1.依旧是不行的, 经过试验,问题出在主函数中的Thread.sleep(1000)上,如果删掉那三个thread.sleep(1000)那么则可以达到楼主预期的效果,根据度娘告诉我的结果,可能是因为有sleep时所有线程不用抢锁,可以都运行,但是当没有sleep时,因为要抢锁,所以一次只能有一个线程在运行。
nickycheng 2015-07-28
  • 打赏
  • 举报
回复
count = count + 1 和 count++不是一个意思嘛! 新的count结果实际是另一个实例。 Jdk会在操作Integer的时候, 进行自动装箱和拆箱. 比如Integer result = Integer(1) + Integer(2). 会变为int 1 + int 2. 然后result呢, 会被装箱成Integer(3) 要想打到效果,把Integer添加final,不要改变Integer的值
cricel 2015-07-28
  • 打赏
  • 举报
回复
楼上说的使用count++会导致count对象编程另外一个新的integer。不是一个实例,但是我试了一下如果我把count++改成count=count+1.依旧是不行的, 经过试验,问题出在主函数中的Thread.sleep(1000)上,如果删掉那三个thread.sleep(1000)那么则可以达到楼主预期的效果,根据度娘告诉我的结果,可能是因为有sleep时所有线程不用抢锁,可以都运行,但是当没有sleep时,因为要抢锁,所以一次只能有一个线程在运行。

50,504

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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