目前共有5篇帖子。 内容转换:不转换▼
 
点击 回复
694 4
【程序】Java线程同步
一派护法 十九级
1楼 发表于:2016-11-7 19:21

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) {
                       
                    }
                }
            }
        }
    }
}

一派护法 十九级
2楼 发表于:2016-11-7 19:21
【输出】
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
一派护法 十九级
3楼 发表于:2016-11-7 19:24
synchronized (this) {
此代码将整个Saler对象锁住,当第一个线程和第二个线程同时访问Saler.tickets变量时,第二个线程将会卡在synchronized那里,等待第一个线程的synchronized语句块执行完毕。
一派护法 十九级
4楼 发表于:2016-11-7 19:26
可以将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) {
                
            }
        }
    }
}


一派护法 十九级
5楼 发表于:2016-11-7 19:31
虽然while语句里的条件确保了tickets不会小于1,但是由于线程在执行过程中可能会卡在synchronized语句上,等到继续执行时tickets可能已被其他线程减为小于1的数,从而出现输出0, -1, -2的情况,这需要通过一个if语句来避免。

回复帖子

内容:
用户名: 您目前是匿名发表
验证码:
(快捷键:Ctrl+Enter)
 

本帖信息

点击数:694 回复数:4
评论数: ?
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2016-11-7 19:31
 
©2010-2024 Arslanbar Ver2.0
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。