Java 多线程同步与死锁

在多线程中如何找到安全问题所在:
1,明确哪些代码是多线程运行代码
2,明确共享数据
3,明确多线程运行代码中哪些代码是操作共享数据的


静态的同步方法中,使用锁是该方法所在类的字节码文件对象,即 类名.class 



前天俺们谈到了加锁,但是在使用加锁的同时又会带来一个问题,就是死锁。什么叫死锁?

所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。   

那么为什么会产生死锁呢?

1.因为系统资源不足。

2.进程运行推进的顺序不合适。   

 3.资源分配不当。            

 学过操作系统的朋友都知道:产生死锁的条件有四个:

1.互斥条件:所谓互斥就是进程在某一时间内独占资源。

2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。

4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

  

例如:     

死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等待,而无法执行的情况。

分析死锁产生的原因不难看出是由访问共享资源顺序不当所造成的,下面写一个造成线程死锁的例子,希望能对大家理解多线程死锁问题有进一步的理解!如果有人需要编写多线程的系统,当操作共享资源时一定要特别的小心,以防出现死锁的情况!

 

  1. package com.oyqh;  
  2.   
  3. public class RunnableTest implements Runnable {  
  4.     private int flag = 1;  
  5.     private static Object obj1 = new Object(), obj2 = new Object();  
  6.   
  7.     public void run() {  
  8.         System.out.println("flag=" + flag);  
  9.         if (flag == 1) {  
  10.             synchronized (obj1) {  
  11.                 System.out.println("我已经锁定obj1,休息0.5秒后锁定obj2去!");  
  12.                 try {  
  13.                     Thread.sleep(500);  
  14.                 } catch (InterruptedException e) {  
  15.                     e.printStackTrace();  
  16.                 }  
  17.                 synchronized (obj2) {  
  18.                     System.out.println("1");  
  19.                 }  
  20.             }  
  21.         }  
  22.         if (flag == 0) {  
  23.             synchronized (obj2) {  
  24.                 System.out.println("我已经锁定obj2,休息0.5秒后锁定obj1去!");  
  25.                 try {  
  26.                     Thread.sleep(500);  
  27.                 } catch (InterruptedException e) {  
  28.                     e.printStackTrace();  
  29.                 }  
  30.                 synchronized (obj1) {  
  31.                     System.out.println("0");  
  32.                 }  
  33.             }  
  34.         }  
  35.     }  
  36.   
  37.     public static void main(String[] args) {  
  38.         RunnableTest run01 = new RunnableTest();  
  39.         RunnableTest run02 = new RunnableTest();  
  40.         run01.flag = 1;  
  41.         run02.flag = 0;  
  42.         Thread thread01 = new Thread(run01);  
  43.         Thread thread02 = new Thread(run02);  
  44.         System.out.println("线程开始喽!");  
  45.         thread01.start();  
  46.         thread02.start();  
  47.     }  
  48. }  
package com.oyqh;

public class RunnableTest implements Runnable {
	private int flag = 1;
	private Object obj1 = new Object(), obj2 = new Object();

	public void run() {
		System.out.println("flag=" + flag);
		if (flag == 1) {
			synchronized (obj1) {
				System.out.println("我已经锁定obj1,休息0.5秒后锁定obj2去!");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (obj2) {
					System.out.println("1");
				}
			}
		}
		if (flag == 0) {
			synchronized (obj2) {
				System.out.println("我已经锁定obj2,休息0.5秒后锁定obj1去!");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (obj1) {
					System.out.println("0");
				}
			}
		}
	}

	public static void main(String[] args) {
		RunnableTest run01 = new RunnableTest();
		RunnableTest run02 = new RunnableTest();
		run01.flag = 1;
		run02.flag = 0;
		Thread thread01 = new Thread(run01);
		Thread thread02 = new Thread(run02);
		System.out.println("线程开始喽!");
		thread01.start();
		thread02.start();
	}
}


 这样就产生了死锁,这是我们过多的使用同步而产生的。我们在java中使用synchonized的时候要考虑这个问题,如何解决死锁,大家可以从死锁的四个条件去解决,只要破坏了一个必要条件,那么我们的死锁就解决了。在java中使用多线程的时候一定要考虑是否有死锁的问题.

 

The other example:

one:

class Ticket implements Runnable
{
	private int tick=100;
	Object obj=new Object();
	boolean flag=true;
	public void run(){
		if (flag)
		{
			while (true)
			{
				synchronized(obj){
					show();
				}
			}
		}
		else 
			while (true)
				show();
	}
	public synchronized void show(){
		synchronized(obj){
				if (tick>0)
				{
					try{Thread.sleep(10);}catch(Exception e){}
					System.out.println(Thread.currentThread().getName()+"...code..."+tick--);
				}
		}
	}
}
class DeadLockDemo
{
	public static void main(String[] args){
		Ticket t=new Ticket();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		t1.start();
		try{Thread.sleep(10);} catch(Exception e){}
		t.flag=false;
		t2.start();
	}
}
 
two:
class TestDeadLock
{
	private boolean flag;
	TestDeadLock(boolean flag){
		this.flag=flag;
	}
	public void run(){
		if (flag)
		{
				synchronized(MyLock.locka){
					System.out.println("if's locka");
					synchronized(MyLock.lockb){
						System.out.println("if's lockb");
					}
				}
		}
		else{
			synchronized(MyLock.lockb){
				System.out.println("else's lockb");
				synchronized(MyLock.locka){
					System.out.println("else's locka");
				}
			}
		}
	}
}


class MyLock
{
	static Object locka=new Object();
	static Object lockb=new Object();

}

class DeadLockTest
{
	public static  void main(String[] args){
		Thread t1=new Thread(new TestDeadLock(true));
		Thread t2=new Thread(new TestDeadLock(false));
		t1.start();
		t2.start();
	}
}
 


 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值