一个缓冲区类BufferLock采用synchronized同步方法,一个发送线程Sender,一个接收线程Receiver,运行结果都不一致,偶尔才对,问题出在哪里呢?运行结果有时是:
Sender put: 1
Receiver get: 1
Receiver get: 2
Sender put: 2
Sender put: 3
Receiver get: 3
Sender put: 4
Receiver get: 4
Sender put: 5
Receiver get: 5public class BufferLock
{
private int value;
private boolean isEmpty=true;
public synchronized void put(int i)
{
while(!isEmpty)
try
{
this.wait();
}
catch(InterruptedException e){}
value=i;
isEmpty=false;
notify();
}
public synchronized int get()
{
while(isEmpty)
try
{
this.wait();
}
catch(InterruptedException e){}
isEmpty=true;
notify();
return value;
}
}
class Sender extends Thread
{
private BufferLock buffer;
public Sender(BufferLock buffer)
{
this.buffer=buffer;
}
public void run()
{
for(int i=1;i<6;i++)
{
buffer.put(i);
System.out.println("Sender put: "+i);
}
}
}
class Receiver extends Thread
{
private BufferLock buffer;
public Receiver(BufferLock buffer)
{
this.buffer=buffer;
}
public void run()
{
for(int i=1;i<6;i++)
System.out.println("\t\t Receiver get: "+buffer.get());
}
public static void main(String args[])
{
BufferLock buffer=new BufferLock();
(new Sender(buffer)).start();
(new Receiver(buffer)).start();
}
}
Sender put: 1
Receiver get: 1
Receiver get: 2
Sender put: 2
Sender put: 3
Receiver get: 3
Sender put: 4
Receiver get: 4
Sender put: 5
Receiver get: 5public class BufferLock
{
private int value;
private boolean isEmpty=true;
public synchronized void put(int i)
{
while(!isEmpty)
try
{
this.wait();
}
catch(InterruptedException e){}
value=i;
isEmpty=false;
notify();
}
public synchronized int get()
{
while(isEmpty)
try
{
this.wait();
}
catch(InterruptedException e){}
isEmpty=true;
notify();
return value;
}
}
class Sender extends Thread
{
private BufferLock buffer;
public Sender(BufferLock buffer)
{
this.buffer=buffer;
}
public void run()
{
for(int i=1;i<6;i++)
{
buffer.put(i);
System.out.println("Sender put: "+i);
}
}
}
class Receiver extends Thread
{
private BufferLock buffer;
public Receiver(BufferLock buffer)
{
this.buffer=buffer;
}
public void run()
{
for(int i=1;i<6;i++)
System.out.println("\t\t Receiver get: "+buffer.get());
}
public static void main(String args[])
{
BufferLock buffer=new BufferLock();
(new Sender(buffer)).start();
(new Receiver(buffer)).start();
}
}
public class BufferLock {
public static void main(String args[]) {
BufferLock buffer = new BufferLock();
(new Sender(buffer)).start();
(new Receiver(buffer)).start();
} private int value;
private boolean isEmpty = true; public void put(int i) {
while (!isEmpty)
try {
this.wait();
} catch (InterruptedException e) {
}
value = i;
isEmpty = false;
notify();
} public int get() {
while (isEmpty)
try {
this.wait();
} catch (InterruptedException e) {
}
isEmpty = true;
notify();
return value;
}
}class Sender extends Thread {
private BufferLock buffer; public Sender(BufferLock buffer) {
this.buffer = buffer;
} public void run() {
synchronized (buffer) {
for (int i = 1; i < 6; i++) {
buffer.put(i);
System.out.println("Sender put: " + i);
}
}
}
}class Receiver extends Thread {
private BufferLock buffer; public Receiver(BufferLock buffer) {
this.buffer = buffer;
} public void run() {
synchronized (buffer) {
for (int i = 1; i < 6; i++)
System.out.println("\t\t Receiver get: " + buffer.get());
}
}}
无论哪个线程锁了buffer,另外一个线程就只能wait了,直到noticy。也就不会出现多次receive或者多次sender的现象了。
锁共享的对象确实可以。这个是书上的例子,用synchronized同步方法,我百度了一下:
synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象f1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。
new Thread(f1).start();
new Thread(f1).start();
为什么这个程序不行呢?
我有一个疑问:
public synchronized int get()
{
while(isEmpty)
try
{
this.wait();
}
catch(InterruptedException e){}
isEmpty=true;
notify(); //会不会在这句语句执行之后还没return的时候发生线程调度了?
return value;
}
2、它锁定的是调用这个同步方法对象。也就是说,当一个对象f1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。
new Thread(f1).start();
new Thread(f1).start();
为什么这个程序不行呢?
这个问题,只要关注下new Thread()里的参数啊。new Thread(f1).start();
new Thread(f1).start();这个是多个线程访问[color=#FF0000]同一个方法,所以锁方法对这两个线程是生效的。[/color],但你这个程序里,不是多个线程调用同一个方法啊,是2个线程都调用了不同的方法啊。
3、//会不会在这句语句执行之后还没return的时候发生线程调度了?
看这里http://www.blogjava.net/qileilove/archive/2011/09/22/359262.html。最主要是这句话:当一个被线程被唤醒 (notify)后,才会进入到就绪队列,等待cpu的调度,主要一句话就是:多线程里,CPU的线程调度我们控制不了。
两篇文章我都看了,收获很多,不过第一篇文章有提到:
如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法。
看起来书上这个例子理论上好像并没有错误,不过我把main方法改成:
BufferLock buffer=new BufferLock();
Sender s=new Sender(buffer);
Receiver r=new Receiver(buffer);
s.start();
r.start();
执行结果要好一点,前面几次都是对的,七八次以后又会出现错误的结果了,不过错误结果的概率小了。
所以看来还有别的原因?