首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

结果不对亚?一个简略短小的例子——采用信号量和同步方法使发送线程与接收线程同步运行

2013-10-23 
结果不对亚?一个简单短小的例子——采用信号量和同步方法使发送线程与接收线程同步运行一个缓冲区类BufferLo

结果不对亚?一个简单短小的例子——采用信号量和同步方法使发送线程与接收线程同步运行
一个缓冲区类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: 5

public 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();
}
}



[解决办法]
锁共享的对象,也就是“buffer”对象。
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的现象了。
[解决办法]
1、synchronized锁定的是哪个对象呢?这个问题可以看这里:http://arthennala.blog.51cto.com/287631/56356,已经非常详细了。
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的线程调度我们控制不了。
[解决办法]
把打印放在put、get方法内部就没问题了,同步锁锁的是get/put方法,而不是run的循环,会有问题。

热点排行