Java多线程(2)——多线程安全(传智播客毕老师视频讲解)

有如下代码

public class RunnableDemo2 implements Runnable
{
	int i=10;
	public  void run()
	{
		for(;i>0;i--)
			System.out.println("...."+Thread.currentThread().getName()+"...."+i);

	}
}
public class Xian1 
{
	static int i;
	public static void main(String[] args) 
	{
		RunnableDemo2  t =new RunnableDemo2();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		t1.start();
		t2.start();
		for(i=0;i<5;i++)
		{
			System.out.println("...main......"+Thread.currentThread().getName());
		}
		System.out.println("over");
	}
}
运行结果如下:

发现有两个10,且其排序不是按照从大到小输出的,此时这种情况属于多线程安全问题。其原因主要是线程0和线程1抢夺执行权引起的,

即当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据

的错误。

解决办法:对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可参与执行!

1、同步

同步的前提:1、必须要有两个或者两个以上的线程。

2、必须是多个线程使用同一个锁。


方法1、同步代码块

      synchonized(对象)//对象如同锁。持有锁的线程可以在同步中执行;没有锁的线程即使获取CPU执行权,也进不去。

      {

需要被同步的代码

       }

public class RunnableDemo2 implements Runnable
{
	int i=10;
	public  void run()
	{
		synchronized(this)
		{
			for(;i>0;i--)
				System.out.println("...."+Thread.currentThread().getName()+"...."+i);
		}
	}
}
运行结果如下:

看见,此时结果没问题。

方法2、同步函数

public class RunnableDemo2 implements Runnable
{
	int i=10;
	public  void run()
	{
		while(i>0)
		show();
	}
	public synchronized void show()
	{
		try{Thread.sleep(100);}catch(Exception e){}
		if(i>0)
		System.out.println("...."+Thread.currentThread().getName()+"...."+i--);
	}
}

运行结果如下:

注意:1、同步函数用的锁是this!

    2、静态同步函数用的锁是Class对象!

  由于静态方法中不能出现this、super关键字,因此其锁不能为this,但可以是任意class对象!

验证代码如下:

public class RunanbleDemo implements Runnable
{
	static int i=100;
	boolean flag=true;
	Object obj=new Object();
	public void setValue(boolean flag)
	{
		this.flag=flag;
	}
	public  void run()
	{
		if (flag)
		{
			while(true)
			{
				synchronized(this)              //验证非静态同步函数的锁是this
			  //synchronized(RunanbleDemo.class)//验证静态同步函数的锁是Class文件
				{//同步代码块儿
					while(i>0)
					{
						try{Thread.sleep(10);}catch(Exception e){}
						//try{wait();}catch(Exception e){}
						System.out.println("...."+Thread.currentThread().getName()+"...."+"Code"+"...."+i--);
					}
				}
			
			}
		}
		else
		{
			while(true)
				show();
		}
	}
	 public synchronized void show()       //非静态同步函数
   //public synchronized static void show()//静态同步函数
	{
		if(i>0)
		{
			try{Thread.sleep(10);}catch(Exception e){}
			System.out.println("...."+Thread.currentThread().getName()+"..............."+"Show"+"...."+i--);
		}
	}
}
public class Xian1 
{
	static int i;
	public static void main(String[] args) 
	{
		RunanbleDemo  t =new RunanbleDemo();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		t1.start();
		try{Thread.sleep(10);}catch(Exception e){}
		t.setValue(false);
		t2.start();
		System.out.println("over");
	}
}
2、单例设计模式——懒汉式的多线程安全问题
方法1、同步函数

public class Single 
{
	private static Single s=null;
	private Single(){}
	public static synchronized Single getSingle()
	{
		if (s==null)
			s=new Single();
			return s;
	}
}
方法2、同步代码块(优化版)
public class Single 
{
	private static Single s=null;
	private Single(){}
	public static  Single getSingle()
	{
		if (s==null)     //这是其优化的地方,这样保证假如许多线程进来,减少了判断syncronized的过程,优化了代码
			synchronized(Single.class)
			{
				if (s==null)
					s=new Single();
			}
			return s;
	}
}
3、死锁
public class DeadLock implements Runnable
{
	static int i=100;
	boolean flag=true;
	Object obj=new Object();
	public void setValue(boolean flag)
	{
		this.flag=flag;
	}
	public  void run()
	{
		if (flag)
		{
			while(true)
			{
				synchronized(DeadLock.class)
				{
					synchronized(this)              //验证非静态同步函数的锁是this
					{
					if(i>0)
					{
						try{Thread.sleep(10);}catch(Exception e){}
						System.out.println("...."+Thread.currentThread().getName()+"...."+"Code"+"...."+i--);
					}
					}
				}
			}
		}
		else
		{
			while(true)
			{
				synchronized(this)             
				  {
					synchronized(DeadLock.class)
					{
						if(i>0)
						{
							try{Thread.sleep(10);}catch(Exception e){}
							System.out.println("...."+Thread.currentThread().getName()+"..............."+"Show"+"...."+i--);
						}
					}
				  }
			}
		}
	}
}
public class DeadLockDemo 
{
	static int i;
	public static void main(String[] args) 
	{
		DeadLock t =new DeadLock();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		t1.start();
		try{Thread.sleep(10);}catch(Exception e){}
		t.setValue(false);
		t2.start();
		System.out.println("over");
	}
}
运行结果为:

即结果在97这儿锁死了,两个线程所持有的锁都不让对方进入,做开发时一定要避免死锁的出现!!





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值