Java多线程之同步与死锁

1.线程的同步
1)The code segments within a program that access the same object from separate, concurrent threads are called “critical sections”。这是临界区的概念。
 
2)同步的两种方式:同步块和同步方法。
 
3)每一个对象都有一个监视器,或者叫做锁。
当线程执行到synchronized的时候,检查传入的实参对象,并得到该对象的锁旗标。如果得不到,那么此线程就会被加入到一个与该对象的锁旗标相关联的等待线程池中,一直等到对象的锁旗标被归还,池中的等待线程就会得到该锁旗标,然后继续执行下去。当线程执行完成同步代码块,就会自动释放它占有的同步对象的锁旗标。一个用于synchronized语句中的对象称为监视器,当一个线程获得了synchronized(object)语句中的代码块的执行权,即意味着它锁定了监视器。
 
4)同步方法利用的是this所代表的对象的锁。
下面实例介绍代码块与方法间的同步。观察this的作用。
《Java多线程之同步与死锁》 《Java多线程之同步与死锁》 public   class  ThreadDemo6  《Java多线程之同步与死锁》 {
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public static void main(String[] args) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》       ThreadTest t 
= new ThreadTest();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》《Java多线程之同步与死锁》       
try 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》           Thread.sleep(
1);//(1)
《Java多线程之同步与死锁》《Java多线程之同步与死锁》
       }
 catch (InterruptedException e) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》           e.printStackTrace();
《Java多线程之同步与死锁》       }

《Java多线程之同步与死锁》       t.str
=new String(method);
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}

《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》
class  ThreadTest  implements  Runnable  《Java多线程之同步与死锁》 {
《Java多线程之同步与死锁》    
private int tickets = 100;
《Java多线程之同步与死锁》    
private int flag=0;
《Java多线程之同步与死锁》    String str 
= new String(“”);
《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public void run() 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》         
if (str.equals(method)) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》           
while (flag==0《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》              sale();
《Java多线程之同步与死锁》           }

《Java多线程之同步与死锁》《Java多线程之同步与死锁》         }
 else 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》           
while (true《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》                
synchronized (this《Java多线程之同步与死锁》{//synchronized (str)//(2)
《Java多线程之同步与死锁》《Java多线程之同步与死锁》
                  if (tickets > 0《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》                     
try 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》                         Thread.sleep(
10);
《Java多线程之同步与死锁》《Java多线程之同步与死锁》                     }
 catch (Exception e) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》                         e.printStackTrace();
《Java多线程之同步与死锁》                     }

《Java多线程之同步与死锁》                     System.out.println(Thread.currentThread().getName()
《Java多线程之同步与死锁》                            
+  is saling ticket  + tickets);
《Java多线程之同步与死锁》                  }
 else return;
《Java多线程之同步与死锁》                }

《Java多线程之同步与死锁》           }

《Java多线程之同步与死锁》         }

《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public synchronized void sale() 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》         
if (tickets > 0《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》           
try 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》              Thread.sleep(
10);
《Java多线程之同步与死锁》《Java多线程之同步与死锁》           }
 catch (Exception e) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》              e.printStackTrace();
《Java多线程之同步与死锁》           }

《Java多线程之同步与死锁》           System.out.println(
track in method sale.);
《Java多线程之同步与死锁》           System.out.println(Thread.currentThread().getName()
《Java多线程之同步与死锁》                  
+  is saling ticket  + tickets);
《Java多线程之同步与死锁》         }
 else flag = 1;
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}

注1,如果不使主线程sleep,很可能两个新建线程都执行同步方法(sale)中的代码。因为,产生并启动第一个线程,这个线程不见得马上开始运行,CPU可能还在原来的main线程上运行,并将str变量设置为”method”,等到第一个线程真正开始运行时,此刻检查到str的值为”method”,所以它将运行sale方法。
注2,如果使用synchronized (str),则两个线程不会同步。
 
5)要时刻考虑CPU会随时切换线程的情况。
 
6)同步是以牺牲程序的性能为代价的。
 
1.1同步代码块
ThreadDemo2.java

《Java多线程之同步与死锁》
《Java多线程之同步与死锁》
class
 ThreadTest 
implements
 Runnable 
《Java多线程之同步与死锁》
{
《Java多线程之同步与死锁》    
private int tickets = 100;
《Java多线程之同步与死锁》    String str 
= new String(“”);
《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public void run() 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》         
while (true《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》           
synchronized (str) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》              
if (tickets > 0《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》                  
try 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》                     Thread.sleep(
10);
《Java多线程之同步与死锁》《Java多线程之同步与死锁》                  }
 catch (Exception e) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》                     e.printStackTrace();
《Java多线程之同步与死锁》                  }

《Java多线程之同步与死锁》                  System.out.println(Thread.currentThread().getName()
《Java多线程之同步与死锁》                         
+  is saling ticket  + tickets);
《Java多线程之同步与死锁》              }
 else return;
《Java多线程之同步与死锁》           }

《Java多线程之同步与死锁》         }

《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}


《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》

public
 
class
 ThreadDemo2 
《Java多线程之同步与死锁》
{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public static void main(String[] args)《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》       ThreadTest t
=new ThreadTest();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}

1.2同步方法

ThreadDemo3.java

《Java多线程之同步与死锁》
《Java多线程之同步与死锁》
class
 ThreadTest 
implements
 Runnable 
《Java多线程之同步与死锁》
{
《Java多线程之同步与死锁》    
private int tickets = 100;
《Java多线程之同步与死锁》    
private int flag=0;
《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public void run() 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》       
while (flag==0)  sale();
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public synchronized void sale() 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》       
if (tickets > 0《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》           
try 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》              Thread.sleep(
10);
《Java多线程之同步与死锁》《Java多线程之同步与死锁》           }
 catch (Exception e) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》              e.printStackTrace();
《Java多线程之同步与死锁》           }

《Java多线程之同步与死锁》           System.out.println(Thread.currentThread().getName()
《Java多线程之同步与死锁》                  
+  is saling ticket  + tickets);
《Java多线程之同步与死锁》       }
else flag=1;
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}


《Java多线程之同步与死锁》《Java多线程之同步与死锁》

public
 
class
 ThreadDemo3 
《Java多线程之同步与死锁》
{
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public static void main(String[] args)《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》       ThreadTest t
=new ThreadTest();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》       
new Thread(t).start();
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}

在同一个类中,使用synchronized关键字定义的若干方法,可以在多个线程之间同步,当有一个线程进入了synchronized修饰的方法(获得监视器),其他线程就不能进入同一个对象的所有使用了synchronized修饰的方法,直到第一个线程执行完它所进入的synchronized修饰的方法为止(离开监视器)。

2.线程的死锁
线程1锁住了对象A的监视器,等待对象B的监视器,线程2锁住了对象B的监视器,等待对象A的监视器,就造成了死锁。
《Java多线程之同步与死锁》 《Java多线程之同步与死锁》 class  A 《Java多线程之同步与死锁》 {
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
synchronized void foo(B b)《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》       String name
=Thread.currentThread().getName();
《Java多线程之同步与死锁》       System.out.println(name
+ enter A.foo);
《Java多线程之同步与死锁》《Java多线程之同步与死锁》       
try 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》           Thread.sleep(
1000);
《Java多线程之同步与死锁》《Java多线程之同步与死锁》       }
 catch (InterruptedException e) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》           e.printStackTrace();
《Java多线程之同步与死锁》       }

《Java多线程之同步与死锁》       System.out.println(name
+ trying to call B.last);
《Java多线程之同步与死锁》       b.last();
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》    
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
synchronized void last()《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》       System.out.println(Thread.currentThread().getName()
《Java多线程之同步与死锁》              
+inside A.last);
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}

《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》
class  B 《Java多线程之同步与死锁》 {
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
synchronized void bar(A a)《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》       String name
=Thread.currentThread().getName();
《Java多线程之同步与死锁》       System.out.println(name
+ enter B.bar);
《Java多线程之同步与死锁》《Java多线程之同步与死锁》       
try 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》           Thread.sleep(
1000);
《Java多线程之同步与死锁》《Java多线程之同步与死锁》       }
 catch (InterruptedException e) 《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》           e.printStackTrace();
《Java多线程之同步与死锁》       }

《Java多线程之同步与死锁》       System.out.println(name
+ trying to call A.last);
《Java多线程之同步与死锁》       a.last();
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》    
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
synchronized void last()《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》       System.out.println(Thread.currentThread().getName()
《Java多线程之同步与死锁》              
+ inside B.last);
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}

《Java多线程之同步与死锁》 
《Java多线程之同步与死锁》《Java多线程之同步与死锁》
public   class  Deadlock  implements  Runnable 《Java多线程之同步与死锁》 {
《Java多线程之同步与死锁》    A a
=new A();
《Java多线程之同步与死锁》    B b
=new B();
《Java多线程之同步与死锁》《Java多线程之同步与死锁》    Deadlock()
《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》         Thread.currentThread().setName(
MainThread);
《Java多线程之同步与死锁》         
new Thread(this).start();
《Java多线程之同步与死锁》         System.out.println(
track after start);
《Java多线程之同步与死锁》         a.foo(b);
《Java多线程之同步与死锁》         System.out.println(
back in main thread);
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public void run()《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》         System.out.println(
track in run);
《Java多线程之同步与死锁》         Thread.currentThread().setName(
RacingThread);
《Java多线程之同步与死锁》         b.bar(a);
《Java多线程之同步与死锁》         System.out.println(
back in other thread);
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》《Java多线程之同步与死锁》    
public static void main(String[]args)《Java多线程之同步与死锁》{
《Java多线程之同步与死锁》         
new Deadlock();
《Java多线程之同步与死锁》    }

《Java多线程之同步与死锁》}

结果:
track after start
MainThread enter A.foo
track in run
RacingThread enter B.bar
MainThread trying to call B.last
RacingThread trying to call A.last
 
3.参考资料
[1]Thinking in Java 3rd

    原文作者:谢芳[Kevin]
    原文地址: http://www.cnblogs.com/xiefang1980/archive/2008/04/21/1163882.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞