|
【程序】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语句来避免。
|