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 }
View Code

此段代码的输出结果是:

  

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--);
            }
        }
        }
View Code

  代码块同步:只需要将需要同步的代码放入synchronized语句之中,形成同步代码块,在同一时刻只有一个线程可以使用该段代码,只有该线程离开这段代码之后,其他的线程才可以使用该段代码(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。


【同步方法】

  除了可以同步代码块之外,也可以同步方法体,只需要在方法的返回类型前面加上synchronized即可。当一个线程使用当前的synchronized方法,其他线程就不可以使用本对象中所有用synchronized修饰的方法,直到一个线程执行完他所进入的方法。

【同步对象】

在整个对象上家锁,即synchronized(对象)。那么其他线程在该类所有的对象上的操作都是加锁的。这种方法往往比较粗暴,在类中只有一个方法加锁,却”屏蔽“了这个对象。

  比较好的做法就会给当前使用的对象加锁。

  synchronized(this)

可以参阅:

http://yamei.blog.51cto.com/4382266/864662

原文地址:https://www.cnblogs.com/plxx/p/3379025.html