zoukankan      html  css  js  c++  java
  • 黑马程序员——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培训期待与您交流! ----------

  • 相关阅读:
    python 安装impala包
    Hive表导出成csv文件
    linux sed命令详解
    Android--Sensor传感器
    Android--ColorMatrix改变图片颜色
    Android--Matrix图片变换处理
    Android--使用Canvas绘图
    Android--从系统Camera和Gallery获取图片优化
    Android--从系统Gallery获取图片
    Android--Tween补间动画
  • 原文地址:https://www.cnblogs.com/runwind/p/4212196.html
Copyright © 2011-2022 走看看