java--线程同步
1 package Test; 2 3 public class Demo9 { 4 public static void main(String[] args) { 5 TestSync2 tt = new TestSync2(); 6 7 // 8 new Thread(tt).start(); 9 new Thread(tt).start(); 10 new Thread(tt).start(); 11 new Thread(tt).start(); 12 } 13 14 } 15 class TestSync2 implements Runnable{ 16 private int ticket = 20; 17 public void run(){ 18 while(true){ 19 if(ticket>0){ 20 try{ 21 Thread.sleep(1000); 22 }catch(Exception e){} 23 System.out.println(Thread.currentThread().getName()+" 出售票: "+ticket--); 24 } 25 } 26 } 27 }
此段代码的输出结果是:
Thread-3 出售票: 10 Thread-2 出售票: 9 Thread-0 出售票: 8 Thread-1 出售票: 7 Thread-2 出售票: 6 Thread-3 出售票: 5 Thread-0 出售票: 4 Thread-1 出售票: 4 Thread-2 出售票: 3 Thread-3 出售票: 2 Thread-1 出售票: 1 Thread-0 出售票: 1 Thread-3 出售票: 0 Thread-2 出售票: -1
很明显数据结果是不对的,这种意外的结果就是要说的“线程安全”问题,即资源访问的同步性问题。
if(tickets>0)
{
System.out.println(Thread.currentThread().getName()+"出售票"+tickets--);
}
即当一个线程运行到if(tickets>0)后,CPU不去执行其它线程中的、可能影响当前线程中的下一句代码的执行结果的代码块,必须等到下一句执行完后才能去执行其它线程中的有关代码块。这段代码就好比一座独木桥,任何时刻,都只能有一个人在桥上行走,程序中不能有多个线程同时在这两句代码之间执行,这就是线程同步
【同步代码块】
synchronized(对象){
需要同步的代码块
}
上面的代码修改
Thread-0 出售票: 10 Thread-3 出售票: 9 Thread-2 出售票: 8 Thread-2 出售票: 7 Thread-2 出售票: 6 Thread-2 出售票: 5 Thread-2 出售票: 4 Thread-1 出售票: 3 Thread-1 出售票: 2 Thread-1 出售票: 1
本次的结果:
while(true){ synchronized(this){ if(ticket>0){ try{ Thread.sleep(1000); }catch(Exception e){} System.out.println(Thread.currentThread().getName()+" 出售票: "+ticket--); } } }
代码块同步:只需要将需要同步的代码放入synchronized语句之中,形成同步代码块,在同一时刻只有一个线程可以使用该段代码,只有该线程离开这段代码之后,其他的线程才可以使用该段代码(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。
【同步方法】
除了可以同步代码块之外,也可以同步方法体,只需要在方法的返回类型前面加上synchronized即可。当一个线程使用当前的synchronized方法,其他线程就不可以使用本对象中所有用synchronized修饰的方法,直到一个线程执行完他所进入的方法。
【同步对象】
在整个对象上家锁,即synchronized(对象)。那么其他线程在该类所有的对象上的操作都是加锁的。这种方法往往比较粗暴,在类中只有一个方法加锁,却”屏蔽“了这个对象。
比较好的做法就会给当前使用的对象加锁。
synchronized(this)
可以参阅:
http://yamei.blog.51cto.com/4382266/864662