解决线程同步带来的访问冲突问题

线程的同步也可以称为并发,由于进程是处理机分配资源的最小单位,

就会出现多个线程共同享用一个资源的想象,在带来方便的同时也带来了访问资源冲突这个严重的问题,

JAVA语言在提供了专门机制解决这种冲突,有效的避免了同一个数据对象被多个线程同时访问



关键字synchronized,在多线程情况下,可以确保资源安全,即线程安全

以前提到的HashTable线程安全,HashMap线程不安全,说的也就是线程同步问题

HashTable的put方法用synchronized关键字修饰,所以它的线程安全



同步又分为了同步块以及同步方法

同步方法:方法前面添加synchronized关键字

同步块:synchronized(引用类型|this|类.class){ }




利用关键字synchronize来解决之前遗留的线程不安全的问题

在博文-[线程的阻塞+通过外部干涉终止一个线程]中,当加入线程休眠模拟网络延迟时,出现了多线程并发错误


1.同步方法

解决方法其实很简单,见代码

public class SynDemo01 {
	public static void main(String[] args) {
		web1 web = new web1();

		Thread t1 = new Thread(web);
		Thread t2 = new Thread(web);

		t1.start();
		t2.start();
	}
}

class web1 implements Runnable{

	public int num=10;
	private boolean flag=true;
	
	@Override
	public void run() {
		while(flag){
			test2();
		}
	}
	
	/**
	 * 线程不安全
	 */
	public void test1(){
		if(num<=0){
			flag=false;
			return;
		}
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		System.out.println(Thread.currentThread().getName()+"抢到了 "+num--);
	}
	
	
	/**
	 * 线程安全
	 */
	public synchronized void test2(){
		if(num<=0){
			flag=false;
			return ;
		}
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		System.out.println(Thread.currentThread().getName()+"抢到了 "+num--);
	}	
}

为方法添加关键字就可以使资源上锁,也就是当t1,t2这两个线程都需要进入到test2方法时,当其中一个进入以后,

就会阻止另一个线程也进入,这样就不会出现线程不安全的问题了

当你的方法添加了synchronize关键字以后,只能被一个线程访问



2.同步块

在方法签名中添加关键字,是将整个方法体都锁定了,所有方法体都只允许一个线程访问

而同步块可以只将需要锁定的部分代码锁定起来

使用同步块就带来了锁定资源和锁定范围的问题

锁定范围不能过大,造成资源利用率低下,也不能过小,没有锁定正确线程还是不安全的

这也是解决多线程并发的难点所在



通过代码实例操作,可以看出来线程安全要比线程不安全慢,线程安全有等待,效率低



你可能感兴趣的:(J2SE)