62,634
社区成员




package com.java.test;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private volatile 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();
}
}
跑了几遍代码,我看出问题是在启动线程那里的sleep,现在分析如下: 1.启动线程时没有sleep,并且synchronized里的是一个对象的变量 如果启动线程之间没有sleep动作,那只会有一个线程会运行,不一定是哪个线程,几个一起抢锁,哪个抢到哪个运行,其它都被阻塞,直到运行的那个线程运行结束,其它就又开始争抢,抢到的开始运行,其它又阻塞,如此循环直到所有线程运行完。 2.启动线程时有sleep,并且synchronized里的是一个对象的变量 那线程是依次启动,不会同时争抢锁,启动的线程都会运行,并且synchronized里的变量都是同步的,即在某个线程里改变了值,另外的线程里值也是随着改变的。 3.synchronized里的是一个对象 假如把.synchronized里的改为LockTest.this,不管启动线程那里是同时启动,还是加了sleep依次启动,都只会有一个线程在运行,即抢到锁的那个,没有sleep时是随机的某个线程,有sleep的是第一启动的线程
public void run() {
// lock.lock();
synchronized(count) {
while(count < 100) {
try {
System.out.println(Thread.currentThread().getName() + " run1: "+count++);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我将run方法中的sleep方法放到打印语句下后,即使你把main方法中的sleep方法去掉,同步块依然失效,大家可以试试。
至于楼主代码当main方法中的sleep方法去掉后可以实现同步,我猜想或许是cup时间片的问题
public void run1() {
synchronized(count) {
while(count < 1000) {
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " run1: "+count++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// lock.unlock();
}
结果和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
Thread-0 run1: 7
Thread-0 run1: 8
Thread-0 run1: 9Java中synchronized同步的对象不能是Integer等类型,因为是Java的自动封箱和解箱操作在作怪。这里的i++实际上是i = new Integer(i+1),所以执行完i++后,i已经不是原来的对象了,同步块自然就无效了。
Java中synchronized同步的对象不能是Integer等类型,因为是Java的自动封箱和解箱操作在作怪。这里的i++实际上是i = new Integer(i+1),所以执行完i++后,i已经不是原来的对象了,同步块自然就无效了。
我试了下,把main方法中Thread.sleep注掉,就好使了。。这是个什么鬼
可能真是这样,int型变量的加减操作导致对象解锁了 http://zhidao.baidu.com/link?url=kTHy33I23SLVfNJy30-MtDrepBkkquHEa9GFzY-oK1PkcW3ohBPSdU5L7eDYKKEFuEVlYYtzpjbL35C9yt_xHbSPbr6ELtjT-KK0s87eFXq
http://zhidao.baidu.com/link?url=kTHy33I23SLVfNJy30-MtDrepBkkquHEa9GFzY-oK1PkcW3ohBPSdU5L7eDYKKEFuEVlYYtzpjbL35C9yt_xHbSPbr6ELtjT-KK0s87eFXq