多线程(二)——线程同步synchronized

线程同步

1.线程同步定义

所谓线程同步,它的真实意思,其实是“排队”,几个线程要对同一资源进行操作时,必须排队依次来进行访问,而不是在同一时刻多个线程对共享资源同时操作。

 

2.问题引入

 

至于为什么要运用线程同步呢?就如我们在多线程(一)中提到的例子买火车票一样,如果多个线程同时去买票就有可能出现余票为负数的情况。

示例代码如下:

public class RunaableTest implements Runnable{

	int ticket=5;
	public static void main(String []args){
		RunaableTest rt=new RunaableTest();
		for(int i=0;i<3;i++){
			new Thread(rt).start();
		}
	}
	public void run(){
		while(true){
			if(ticket>0){
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("线程"+Thread.currentThread().getName()+"买票之后还有余票:ticket"+ticket--+"张");
			}
		}
	}
}

程序运行结果如下:



 

由以上例子可以看出,当我们让线程休眠一段时间,再去执行ticket--,这样在程序的最后出现了卖出负票的问题,这样显然是不对的,为什么会这样呢?我们可以猜测:在if循环中同一时刻至少存在两个线程,第一个线程还没来得及进行ticcket--操作时,第二个线程经过判断满足if循环条件即ticket>0也进入循环体内,这样一来就会出现其实没票了,但还能卖出票的情况。

 

3.解决办法

 

出现上面的问题,只是因为多个线程对if循环的条件同时进行了判断,所以在多线程操作同一个资源时我们只需要对其有一个限制,即设定同一时刻只能有一个线程去访问共享的资源,如此一来问题就可以轻松的解决了。

而在JAVA中我们可以通过关键字synchronized来解决这个问题,实现线程之间的同步。而synchronized的使用方法有两种,可以通过同步代码块和同步方法两种方式来完成。

 

1.同步代码块:

public  void run(){
		while(true){
			synchronized(this){
				if(ticket>0){
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("线程"+Thread.currentThread().getName()+"买票之后还有余票:ticket"+ticket--+"张");
				}
			}
		}
	}

 

 

2.同步方法:

public synchronized void run(){
		while(true){
			if(ticket>0){
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("线程"+Thread.currentThread().getName()+"买票之后还有余票:ticket"+ticket--+"张");
			}
		}
	}

 

    两种实现方式的运行结果是一样的,结果如下:



 

由此我们便可完成线程同步,解决多个线程同一时刻访问同一对象的问题啦!!!

 

PS:线程中还有死锁的概念,所谓死锁,就是指两个线程都在等对方完成。举个例子,假设只有一碗饭,一双筷子,二者合到一起,才能吃到饭,但是饭在甲的手中,而筷子在乙的手中,甲,乙都在等着对方先给,就这样僵持着,最终的结果是甲乙都吃不到饭,这就是死锁的概念。程序出现死锁的情况有可能是因为过多的同步,所以在多个线程共享同一资源进行同步的同时,也要注意避免出现死锁的状况哈。。。。。。

猜你喜欢

转载自lxl-yes777.iteye.com/blog/1772320