黑马程序员——JAVA基础之多线程的安全问题

------- android培训java培训期待与您交流! ----------

 

导致多线程出现问题的一个特殊的状态:就绪。具备了执行资格,但是还没有获取资源。

 


导致安全问题的出现的原因:


    1. 多个线程访问出现延迟。
    2.线程随机性。

 

同步代码块:


      Java对于多线程的安全问题提供了专业的解决方式。就是同步代码块。

 

同步代码块格式:


     synchronized(对象)
      {
             需要被同步的代码
      }


   对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

同步的前提:


       1、必须要有两个或者两个以上的线程。
       2、必须是多个线程使用同一个锁。

                        必须保证同步中只能有一个线程在运行。

 

同步代码块的优缺点:


好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,

 

还是经典的卖票程序,经过安全处理后:

 

/**
 * 
 * 解决卖票程序的安全问题
 * 		同步代码块  synchronized
 *
 */
public class SynchronizedDemo 
{
	public static void main(String[] args)
	{
		Tic t = new Tic();
		
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		Thread t4 = new Thread(t);
		
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}

class Tic implements Runnable
{
	private int tic = 100;
	Object obj = new Object();
	
	public void run()
	{
		while (tic>0)
		{
			synchronized(obj)
			{
				//为了效果明显这里用了sleep方法,此方法需要指定睡眠时间,单位毫秒,应用需要try{}catch{}
				try{Thread.sleep(10);}catch(Exception e){}
				System.out.println(Thread.currentThread().getName()+"--------"+tic--);
			}
		}
	}
} 


如何找问题:
     1,明确哪些代码是多线程运行代码。
     2,明确共享数据。
     3,明确多线程运行代码中哪些语句是操作共享数据的。

    同步函数特点:

     如果参数没有就默认是this. 

    如果被静态修饰就是XX.class。因为静态没有this 

/**
* 需求:
* 银行有一个金库。
* 有两个储户分别存300员,每次存100,存3次。
*/
class Bank
{
	private int sum;
	//下面调用用了多线程,所以这里需要同步
	public synchronized void add(int num)//同步函数
	{
		sum += num;
		System.out.println("sum = "+sum);
	}
}

class Cus implements Runnable
{
	//这里只能创建一个银行,所以放在run外面
	private Bank b = new Bank();
	
	public void run()
	{
		for (int i=0;i<3 ;i++ )
		{
			b.add(100);			
		}
	}
}

class BankDemo
{
	public static void main(String[] args) 
	{
		Cus c = new Cus();
		
		Thread c1 = new Thread(c);
		Thread c2 = new Thread(c);
		
		c1.start();
		c2.start();
	}
}


 

在多线程里面会发生一种叫做死锁的情况,应尽量避免死锁的发生。

 

死锁:是指多个进程因竞争系统资源或相互通信而造成的一种僵局

 

死锁产生的原因:
1.竞争资源:多个进程竞争资源,而资源又不能同时满足其需求
2.进程推进顺序不当:进程申请资源和释放资源的顺序不当


注意:
1.死锁是因资源竞争造成的僵局
2.死锁至少涉及两个进程
3.死锁与部分进程及资源相关


解决死的基本方法:
1.预防死锁:设置某些限制条件,通过破坏死锁产生的条件来预防死锁
2.避免死锁:在资源的动态分配过程中,用某种方法来防止系统进入不安全状态
3.检测死锁及解除死锁:系统定期检测是否出现死锁,若出现则解除死锁

/**
 * 
 * 死锁程序的演示
 * 		尽量避免!!!
 *
 */
public class MyLock 
{
	public static void main(String[] args)
	{		
		Thread t1 = new Thread(new Test(true));
		Thread t2 = new Thread(new Test(false));
		
		t1.start();
		t2.start();
	}
}

//声明一个类,里面创建两个对象,代表两个锁
class Lock
{
	static Object locka = new Object();//静态只能访问静态
	static Object lockb = new Object();
}

//声明一个类,实现Runnable接口,演示死锁的多线程类
class Test implements Runnable
{
	private boolean flag;
	Test (boolean flag)
	{
		this.flag = flag;
	}
	
	public void run()
	{
		if (flag)
		{
			while(true)
			{
				synchronized (Lock.locka)
				{
					System.out.println(Thread.currentThread().getName()+"------"+"if locka");
					synchronized (Lock.lockb)
					{
						System.out.println(Thread.currentThread().getName()+"------"+"if lockb");
					}
				}
			}
		}
		else
		{
			while (true)
			{
				synchronized (Lock.lockb)
				{
					System.out.println(Thread.currentThread().getName()+"------"+"else lockb");
					synchronized (Lock.locka)
					{
						System.out.println(Thread.currentThread().getName()+"------"+"else locka");
					}
				}
			}
		}
	}
}


 

------- android培训java培训期待与您交流! ----------

原文地址:https://www.cnblogs.com/runwind/p/4212196.html