多线程同步以及线程的锁机制,避免死锁等问题

话外语:我胡汉三又回来啦!!!

----------------------------------------------------------------------------------------------------------------------------------

Java中线程同步有一个典型的问题就是“生产者消费者”问题。

用两个线程模拟存票售票过程:假定开始售票处并没有票,一个线程往里面存票,另一个线程则往外售票。

新建一个票类对象,让存票和售票线程都访问它。(两个线程共享一个数据并对其进行操作)

package multi_thread;

public class ProducerAndConsumer {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Tickets t = new Tickets(10);
		new Producer(t).start();
		new Consumer(t).start();
	}
}

class Tickets{
	int number =0;		//票号
	int size;			//总票数
	boolean available = false;			//表示目前是否有票可售
	public Tickets(int size) {
		this.size = size;
	}
}

class Producer extends Thread{
	Tickets t = null;
	public Producer(Tickets t ) {
		this.t = t;
	}
	public void run() {
		while( t.number < t.size) {
			System.out.println("Producer puts ticket "+(++t.number));
			t.available = true;
		}
	}
}

class Consumer extends Thread{
	Tickets t = null;
	int i=0;
	public Consumer (Tickets t ) {
		this.t = t;
	}
	public void run() {
		while( i< t.size) {
			if(t.available==true && i<=t.number)
				System.out.println("Consumer buys ticket "+(++i));
			if(i==t.number)
				t.available = false;
		}
	}
}

运行结果:

Producer puts ticket 1
Producer puts ticket 2
Producer puts ticket 3
Producer puts ticket 4
Producer puts ticket 5
Producer puts ticket 6
Producer puts ticket 7
Producer puts ticket 8
Producer puts ticket 9
Producer puts ticket 10
Consumer buys ticket 1
Consumer buys ticket 2
Consumer buys ticket 3
Consumer buys ticket 4
Consumer buys ticket 5
Consumer buys ticket 6
Consumer buys ticket 7
Consumer buys ticket 8
Consumer buys ticket 9
Consumer buys ticket 10

运行结果是先把票全部生产完然后再售票。(为啥不是边生产边售票呢???)

然后朕试着把调用生产票和消费票的顺序改变了一下,就变成边生产边售票了。。。

new Producer(t).start();
new Consumer(t).start();

变成

new Consumer(t).start();
new Producer(t).start();
具体代码见下:
package multi_thread;

public class ProducerAndConsumer {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Tickets t = new Tickets(10);
		new Consumer(t).start();
		new Producer(t).start();
	}
}

class Tickets{
	int number =0;		//票号
	int size;			//总票数
	boolean available = false;			//表示目前是否有票可售
	public Tickets(int size) {
		this.size = size;
	}
}

class Producer extends Thread{
	Tickets t = null;
	public Producer(Tickets t ) {
		this.t = t;
	}
	public void run() {
		while( t.number < t.size) {
			System.out.println("Producer puts ticket "+(++t.number));
			t.available = true;
		}
	}
}

class Consumer extends Thread{
	Tickets t = null;
	int i=0;
	public Consumer (Tickets t ) {
		this.t = t;
	}
	public void run() {
		while( i< t.size) {
			if(t.available==true && i<=t.number)
				System.out.println("Consumer buys ticket "+(++i));
			if(i==t.number)
				t.available = false;
		}
	}
}

运行结果:(运行结果也是随机的,每次都不一样,但总是先有票才能后售票)

Producer puts ticket 1
Producer puts ticket 2
Consumer buys ticket 1
Producer puts ticket 3
Consumer buys ticket 2
Producer puts ticket 4
Consumer buys ticket 3
Producer puts ticket 5
Consumer buys ticket 4
Producer puts ticket 6
Producer puts ticket 7
Producer puts ticket 8
Producer puts ticket 9
Producer puts ticket 10
Consumer buys ticket 5
Consumer buys ticket 6
Consumer buys ticket 7
Consumer buys ticket 8
Consumer buys ticket 9
Consumer buys ticket 10

以上两端代码运行结果不一样,应该是和CPU的调度有关吧!

第一段代码由于生产者线程在前面,所以CPU资源就先一直给它占据了。由于它生产完票的时间也没有很长啦(就10张票),所以它就生产完了,然后再售票!(为了证明我的说法是正确的,我把生产的票数改成了100,果真,就变成生产和消费交错进行了。因为100张票还是挺多的,CPU资源也不可能一直都给生产者线程一个人占据,就会出现交错进行的情况)

而第二段代码,消费者在前面,它也确实是先执行的。但是在它执行期间由于无票可售,所以它没有输出语句到屏幕(它在执行,只是我们没有看到)。等它执行一段时间后,就生产者执行,然后就出现这样的结果了。

多线程同步以及线程的锁机制,避免死锁等问题_第1张图片

Java对线程同步其实是提供了方法的,关键字synchronized,实现互斥。

synchronized(对象){代码段}

synchronized的功能是:首先判断对象的锁是否在,如果在就获得锁,然后就可以执行紧随其后的代码段;如果对象的锁不在(已经被其他线程拿走),就进入等待状态,直到获得锁。

当被synchronized限定的代码段执行完,就释放锁。

你可能感兴趣的:(Java)