|  | 【程序】Java线程同步 | 
                
          |   一派掌门 二十级 | 
              public class Test {
 
 public static void main(String[] args) {
 Saler s = new Saler();
 for (int i = 1; i <= 4; i++) {
 Thread t = new Thread(s);
 t.setName("Seller " + i);
 t.start();
 }
 }
 
 }
 
 public class Saler implements Runnable {
 private int tickets = 100;
 
 @Override
 public void run() {
 String name = Thread.currentThread().getName();
 while (tickets > 0) {
 synchronized (this) {
 if (tickets > 0) { // 不能省略!否则会出现0, -1, -2被卖出的情况
 System.out.println(name + ": " + tickets);
 tickets--;
 try {
 Thread.sleep((long)(Math.random() * 1500));
 } catch (InterruptedException e) {
 
 }
 }
 }
 }
 }
 }
 
 
 | 
                
          |   一派掌门 二十级 | 
              【输出】Seller 1: 100
 Seller 3: 99
 Seller 3: 98
 Seller 3: 97
 Seller 3: 96
 Seller 4: 95
 Seller 4: 94
 Seller 4: 93
 Seller 4: 92
 Seller 4: 91
 Seller 4: 90
 Seller 4: 89
 Seller 4: 88
 Seller 4: 87
 Seller 4: 86
 Seller 4: 85
 Seller 2: 84
 Seller 4: 83
 Seller 3: 82
 Seller 3: 81
 Seller 3: 80
 Seller 3: 79
 Seller 3: 78
 Seller 3: 77
 Seller 3: 76
 Seller 3: 75
 Seller 3: 74
 Seller 3: 73
 Seller 3: 72
 Seller 3: 71
 Seller 1: 70
 Seller 1: 69
 Seller 3: 68
 Seller 3: 67
 Seller 3: 66
 Seller 3: 65
 Seller 4: 64
 Seller 2: 63
 Seller 2: 62
 Seller 2: 61
 Seller 2: 60
 Seller 2: 59
 Seller 2: 58
 Seller 4: 57
 Seller 3: 56
 Seller 1: 55
 Seller 1: 54
 Seller 1: 53
 Seller 3: 52
 Seller 3: 51
 Seller 3: 50
 Seller 4: 49
 Seller 4: 48
 Seller 4: 47
 Seller 4: 46
 Seller 4: 45
 Seller 4: 44
 Seller 4: 43
 Seller 4: 42
 Seller 2: 41
 Seller 2: 40
 Seller 2: 39
 Seller 4: 38
 Seller 3: 37
 Seller 3: 36
 Seller 3: 35
 Seller 3: 34
 Seller 3: 33
 Seller 3: 32
 Seller 3: 31
 Seller 3: 30
 Seller 3: 29
 Seller 3: 28
 Seller 1: 27
 Seller 1: 26
 Seller 1: 25
 Seller 3: 24
 Seller 3: 23
 Seller 3: 22
 Seller 3: 21
 Seller 4: 20
 Seller 4: 19
 Seller 2: 18
 Seller 4: 17
 Seller 4: 16
 Seller 4: 15
 Seller 4: 14
 Seller 3: 13
 Seller 3: 12
 Seller 3: 11
 Seller 3: 10
 Seller 3: 9
 Seller 3: 8
 Seller 3: 7
 Seller 1: 6
 Seller 1: 5
 Seller 3: 4
 Seller 4: 3
 Seller 2: 2
 Seller 2: 1
 
 | 
|
        
                
          |   一派掌门 二十级 | 
              synchronized (this) {此代码将整个Saler对象锁住,当第一个线程和第二个线程同时访问Saler.tickets变量时,第二个线程将会卡在synchronized那里,等待第一个线程的synchronized语句块执行完毕。
 | 
|
        
                
          |   一派掌门 二十级 | 
              可以将synchronized语句块单独写成一个函数,这样该函数就不能同时被两个线程执行:public class Saler implements Runnable {
 private int tickets = 100;
 
 @Override
 public void run() {
 String name = Thread.currentThread().getName();
 while (tickets > 0) {
 sell(name);
 }
 }
 
 private synchronized void sell(String name) {
 if (tickets > 0) { // 不能省略!否则会出现0, -1, -2被卖出的情况
 System.out.println(name + ": " + tickets);
 tickets--;
 try {
 Thread.sleep((long)(Math.random() * 1500));
 } catch (InterruptedException e) {
 
 }
 }
 }
 }
 
 
 
 | 
|
        
                
          |   一派掌门 二十级 | 
              虽然while语句里的条件确保了tickets不会小于1,但是由于线程在执行过程中可能会卡在synchronized语句上,等到继续执行时tickets可能已被其他线程减为小于1的数,从而出现输出0, -1, -2的情况,这需要通过一个if语句来避免。             | 
|