您的位置:首页 > 编程语言 > Java开发

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

2014-09-11 12:33 519 查看
有如下代码

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这儿锁死了,两个线程所持有的锁都不让对方进入,做开发时一定要避免死锁的出现!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: