线程安全

一、产生线程安全的原因

(1)多个线程在操作共享数据

(2)操作共享数据的线程代码有多条

结论:当一个线程在执行操作共享数据的多条代码过程中,其他线程参与运算,就会导致线程安全问题的产生。

二、解决方案:同步锁,同步锁分为两种如下:

(1)同步锁代码块

	Synchronized(对象){
		//code;
	}


(2)同歩锁函数

	public synchronized void show(){
		//code;
	}

 同步锁函数和同步代码块的区别:

①同步函数的锁是固定的this;

②同步代码块的锁是任意的对象;

③静态的同步函数使用的锁是该函数所属字节码文件对象,可以用getClass()方法获取,也可以用当前类名.class获取;

(3)使用同歩锁的前提:必须有多个线程并同时使用同一个锁;

三、死锁原因

(1)同步锁嵌套

			synchronized(MyLocked.locka){
				System.out.println(Thread.currentThread().getName()+" if locka....");
				synchronized(MyLocked.lockb){
					System.out.println(Thread.currentThread().getName()+" if lockb....");
				}
			}


(2)线程间的通讯,多个线程在处理同一个资源,但任务却不同

//资源
class Resource
{
	String name;
	String sex;
}


//输入
class Input implements Runnable
{
	Resource r ;
//	Object obj = new Object();
	Input(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			synchronized(r)
			{
				if(x==0)
				{
					r.name = "mike";
					r.sex = "nan";
				}
				else
				{
					r.name = "丽丽";
					r.sex = "女女女女女女";
				}
			}
			x = (x+1)%2;

		}
	}
}
//输出
class Output implements Runnable
{

	Resource r;
//	Object obj = new Object();
	Output(Resource r)
	{
		this.r = r;
	}

	public void run()
	{
		while(true)
		{
			synchronized(r)
			{
				System.out.println(r.name+"....."+r.sex);
			}
		}
	}
}



class  ResourceDemo
{
	public static void main(String[] args) 
	{
		//创建资源。
		Resource r = new Resource();
		//创建任务。
		Input in = new Input(r);
		Output out = new Output(r);
		//创建线程,执行路径。
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		//开启线程
		t1.start();
		t2.start();
	}
}


四、等待/唤醒机制

(1)wait();让线程处于冻结状态,被wait的线程会被存储到线程池中;

(2)notify();唤醒线程池中一个线程(任意);

(3)notifyAll();唤醒线程池中的所有线程;

总结:这些方法都必须能定义在同步锁中,因为这些方法是用于操作线程状态的方法,必须能要明确到底操作的是哪个锁上的线程




为什么操作线程的方法wait notify notifyAll定义在了Object类中? 
因为这些方法是监视器的方法。监视器其实就是锁。锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。


五、示例如下:


资源类:

package com.edu.csu.syn;

public class Resource {
	
	private String name;
	private String sex;
	private boolean flag = false;
	
	public synchronized void set(String name,String sex){
		if(flag)
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			this.name = name;
			this.sex = sex;
			flag = true;
			this.notify();
		
	}
	
	public synchronized void out(){
		if(!flag)
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		System.out.println(name+"......"+sex);
		flag = false;
		this.notify();
	}
}

输入类:

package com.edu.csu.syn;

public class Input implements Runnable {
	
	private Resource r;
	
	public Input(Resource r){
		this.r = r;
	}

	@Override
	public void run() {
		int x = 0;
		while(true){
			if (x == 0) {
				r.set("mike", "nan");
			} else {
				r.set("丽丽", "女女女女");
			}

			x = (x + 1) % 2;
		}
	}

}

输出类:

package com.edu.csu.syn;

public class Output implements Runnable {
	
	private Resource r;
	
	public Output(Resource r){
		this.r = r;
	}
	@Override
	public void run() {
		while(true){
			r.out();
		}
	}

}

测试类:

package com.edu.csu.syn;

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//创建资源
		Resource r = new Resource();
		//创建任务
		Input i = new Input(r);
		Output o = new Output(r);
		//创建线程,执行任务
		Thread t = new Thread(i);
		Thread t1 = new Thread(o);
		//开启线程
		t.start();
		t1.start();
	}

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值