线程同步:用来协调多个线程访问同一资源
/* * 线程同步的例子 * */ public class Test { public static void main(String[] args) { //创建两个线程并执行同一条语句 Run r=new Run(); Thread t1=new Thread(r,"t1"); Thread t2=new Thread(r,"t2"); t1.start(); t2.start(); } } class Run implements Runnable{ Timer t=new Timer(); //两个开始的线程调用同一个类中的方法 public void run(){ t.add(Thread.currentThread().getName()); } } class Timer{ int num=0; //计数 Thread t=new Thread(); //当第一个线程执行完计数,睡眠1ms时,第二个线程开始执行计数并睡眠1ms,然后第一个线程打印, //接着第二个线程打印,打印时计数以累加到2. public void add(String ThreadName){ num++; try { t.sleep(1); } catch (InterruptedException e) { } System.out.println(ThreadName+"第"+num+"次执行"); } }
对象互斥锁:每个对象对应一个称为互斥锁的标记,这个标记保证在任何时刻,只有一个线程访问该对象。
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
/* * 避免线程同步。 * */ public class Test { public static void main(String[] args) { //创建两个线程并执行同一条语句 Run r=new Run(); Thread t1=new Thread(r,"t1"); Thread t2=new Thread(r,"t2"); t1.start(); t2.start(); } } class Run implements Runnable{ Timer t=new Timer(); //两个开始的线程调用同一个类中的方法 public void run(){ t.add(Thread.currentThread().getName()); } } class Timer{ int num=0; //计数 Thread t=new Thread(); public synchronized void add(String ThreadName){ //通过关键字synchronized,在执行方法的过程中锁定当前对象。 // synchronized (this){ num++; try { t.sleep(1); } catch (InterruptedException e) { } System.out.println(ThreadName+"第"+num+"次执行"); //} } }
死锁:线程A锁住了对象a,线程B锁住了对象b。而线程A需要对象b才能继续执行
线程B需要对象a才能继续执行
/* * 线程死锁 * */ public class Test { public static void main(String[] args) { //创建两个线程执行不同语句 Run r1=new Run(); Run r2=new Run(); r1.flag=1; r2.flag=0; Thread t1=new Thread(r1); Thread t2=new Thread(r2); t1.start(); t2.start(); } } class Run implements Runnable{ int flag=1; //通过flag的值区分两个不同线程执行的不同操作 static Object o1=new Object(),o2=new Object(); //flag==1的线程无法得到o2,flag==0的线程无法得到o1,进入死锁状态 public void run(){ System.out.println("flag="+flag); //flag==1的线程先锁住o1,在锁o2 if(flag==1){ synchronized(o1){ try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized(o2){ System.out.println("1"); } } } //flag==1的线程先锁住o2,在锁o1 if(flag==0){ synchronized(o2){ try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized(o1){ System.out.println("0"); } } } } }
尽量只锁定一个对象
一个方法执行后一个线程锁定了一个对象,另一个线程可以访问未锁定对象的方法
/* * 线程死锁 * */ public class Test { public static void main(String[] args) { //创建一个线程执行语句 Run r=new Run(); Thread t=new Thread(r); t.start(); //使线程锁定run() try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } r.getb(); } } class Run implements Runnable{ int b=100; public void run(){ synchronized(this){ b=1000; try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("runner:b="+b); } } public void getb(){ System.out.println("m2:b="+b); } }
一个方法执行后一个线程锁定了一个对象,另一个线程不可以访问另一个锁定对象的方法,只有当先执行的方法执行完后,另一个线程才可以访问另一个锁定对象的方法
/* * 线程死锁 * */ public class Test { public static void main(String[] args) { Run r=new Run(); Thread t=new Thread(r); t.start(); try { Thread.sleep(8000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } r.m2(); System.out.println(r.b); } } class Run implements Runnable{ int b=100; public synchronized void m1(){ b=1000; try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run(){ m1(); System.out.println("runner:b="+b); } public synchronized void m2(){ b=2000; System.out.println("m2:b="+b); } }