线程同步锁对象不同导致的安全问题及解决办法

来源:互联网 发布:免费网络电话软件排名 编辑:程序博客网 时间:2024/05/18 05:40

  线程同步锁的对象有三个:

1)、objcet对象

2)、this对象

3)、class文件对象

   总结:

    线程同步锁对象是this,若是静态函数,则是类名.class

1、若对一个对象的共享代码进行同步锁时,若使用不同的锁,存在线程安全问题

例如:

<pre name="code" class="java">class Ticket implements Runnable{private String name;private int  ticket=20;boolean flag;Object obj = new Object();Ticket(String name){this.name = name;}public  void run(){if(flag==true){while(true){//如下同步的锁对象是objcetsynchronized(obj){if(ticket > 0){try{Thread.sleep(10);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+"  "+name+"code..."+ticket--);}}}}elsewhile(true){show();}}//如下函数同步的锁对象是thispublic synchronized void show(){if(ticket > 0){try{Thread.sleep(10);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+"  "+name+"show..."+ticket--);}}}public class ThreadDemo {public static void main(String[] args) {Ticket t1 = new Ticket("t1");Thread tt1 = new Thread(t1);Thread tt2= new Thread(t1);tt1.start();try{Thread.sleep(10);}catch(InterruptedException e){}t1.flag=true;tt2.start();}}

运行结果是:

Thread-0  t1show...20Thread-1  t1code...19Thread-0  t1show...18Thread-1  t1code...17Thread-0  t1show...16Thread-1  t1code...15Thread-0  t1show...14Thread-1  t1code...13Thread-0  t1show...12Thread-1  t1code...11Thread-0  t1show...10Thread-1  t1code...9Thread-0  t1show...8Thread-1  t1code...7Thread-0  t1show...6Thread-1  t1code...5Thread-1  t1code...4Thread-0  t1show...3Thread-1  t1code...2Thread-0  t1show...1Thread-1  t1code...0
运行结果出现ticket为0的情况,因为同步锁的对象不同,分别是object和this对象

2、若共享操作用的是同一个锁对象,则结果正确,修改后的代码如下:

class Ticket implements Runnable{private String name;private int  ticket=20;boolean flag;Object obj = new Object();Ticket(String name){this.name = name;}public  void run(){if(flag==true){while(true){//如下同步的锁对象是thissynchronized(this){if(ticket > 0){try{Thread.sleep(10);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+"  "+name+"code..."+ticket--);}}}}elsewhile(true){show();}}//如下函数同步的锁对象是thispublic synchronized void show(){if(ticket > 0){try{Thread.sleep(10);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+"  "+name+"show..."+ticket--);}}}
运行后结果是:

Thread-0  t1code...20Thread-0  t1code...19Thread-0  t1code...18Thread-0  t1code...17Thread-0  t1code...16Thread-0  t1code...15Thread-0  t1code...14Thread-0  t1code...13Thread-0  t1code...12Thread-0  t1code...11Thread-0  t1code...10Thread-0  t1code...9Thread-0  t1code...8Thread-0  t1code...7Thread-0  t1code...6Thread-0  t1code...5Thread-0  t1code...4Thread-0  t1code...3Thread-0  t1code...2Thread-0  t1code...1

3、若共享方法是静态方法时且锁对象是this时,还存在线程安全问题

class Ticket implements Runnable{private String name;private static int  ticket=20;boolean flag;Object obj = new Object();Ticket(String name){this.name = name;}public  void run(){if(flag==true){while(true){//如下同步的锁对象是objcetsynchronized(obj){if(ticket > 0){try{Thread.sleep(10);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+"  "+name+"code..."+ticket--);}}}}elsewhile(true){show();}}public static synchronized void show(){if(ticket > 0){try{Thread.sleep(10);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+"  "+name+"show..."+ticket--);}}}public class ThreadDemo {public static void main(String[] args) {Ticket t1 = new Ticket("t1");Thread tt1 = new Thread(t1);Thread tt2= new Thread(t1);tt1.start();try{Thread.sleep(10);}catch(InterruptedException e){}t1.flag=true;tt2.start();}}
运行结果是:

Thread-0  t1show...20Thread-1  t1code...19Thread-0  t1show...18Thread-1  t1code...17Thread-0  t1show...16Thread-1  t1code...15Thread-0  t1show...14Thread-1  t1code...13Thread-0  t1show...12Thread-1  t1code...11Thread-0  t1show...10Thread-1  t1code...9Thread-0  t1show...8Thread-1  t1code...7Thread-0  t1show...6Thread-1  t1code...5Thread-1  t1code...4Thread-0  t1show...3Thread-1  t1code...2Thread-0  t1show...1Thread-1  t1code...0
分析原因后发现:静态函数在内存中不存在,但是有该类对应的字节码文件

优化后的代码是:

class Ticket implements Runnable{private String name;private static int  ticket=20;boolean flag;Object obj = new Object();Ticket(String name){this.name = name;}public  void run(){if(flag==true){while(true){//如下同步的锁对象是<span style="font-family: Arial, Helvetica, sans-serif;">Ticket.class</span>synchronized(Ticket.class){if(ticket > 0){try{Thread.sleep(10);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+"  "+name+"code..."+ticket--);}}}}elsewhile(true){show();}}//含有static修饰符的函数同步的锁对象是<span style="font-family: Arial, Helvetica, sans-serif;">Ticket.class</span>public static synchronized void show(){if(ticket > 0){try{Thread.sleep(10);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+"  "+name+"show..."+ticket--);}}}public class ThreadDemo {public static void main(String[] args) {Ticket t1 = new Ticket("t1");Thread tt1 = new Thread(t1);Thread tt2= new Thread(t1);tt1.start();try{Thread.sleep(10);}catch(InterruptedException e){}t1.flag=true;tt2.start();}}
运行后的结果是:

Thread-0  t1code...20Thread-0  t1code...19Thread-0  t1code...18Thread-0  t1code...17Thread-0  t1code...16Thread-0  t1code...15Thread-0  t1code...14Thread-0  t1code...13Thread-0  t1code...12Thread-0  t1code...11Thread-0  t1code...10Thread-0  t1code...9Thread-0  t1code...8Thread-0  t1code...7Thread-0  t1code...6Thread-0  t1code...5Thread-0  t1code...4Thread-0  t1code...3Thread-0  t1code...2Thread-0  t1code...1








1 0
原创粉丝点击