> 类库下载 > java类库 > [JAVA 동시 프로그래밍 실습] Lock Sequence 교착상태

[JAVA 동시 프로그래밍 실습] Lock Sequence 교착상태

高洛峰
풀어 주다: 2016-11-17 13:39:15
원래의
1913명이 탐색했습니다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

package cn.study.concurrency.ch10;

 

public class Account {

    private String staffAccount;    //账号

    private String passWord;    //密码

    private int balance; //账户余额

     

    public Account(int money) {

        this.balance = money;

    }

     

    public String getStaffAccount() {

        return staffAccount;

    }

    public void setStaffAccount(String staffAccount) {

        this.staffAccount = staffAccount;

    }

    public String getPassWord() {

        return passWord;

    }

    public void setPassWord(String passWord) {

        this.passWord = passWord;

    }

     

    public void debit(int amount)

    {

        System.out.println("转出账户:" + amount);

    }

     

    public void credit(int amount)

    {

        System.out.println("转入账户:" + amount);

    }

    public int getBalance() {

        return balance;

    }

    public void setBalance(int balance) {

        this.balance = balance;

    }

     

}

로그인 후 복사

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

package cn.study.concurrency.ch10;

 

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

 

import javax.naming.InsufficientResourcesException;

 

/**

 * 通过制定确定的锁顺序来避免死锁

 * @author xiaof

 *

 */

public class DeathLock {

    public void transferMoney(Account fromAccount, Account toAccount, int amount) throws InsufficientResourcesException

    {

        synchronized(fromAccount)

        {

            synchronized(toAccount)

            {

                //按参数的顺序上锁,这个依据参数的调用方法的顺序

                if(fromAccount.getBalance() < amount)

                {

                    //账户余额不足,无法转账

                    throw new InsufficientResourcesException();

                }

                else

                {

                    fromAccount.debit(amount);

                    toAccount.credit(amount);

                }

            }

        }

    }

    /**

     * 这个用来在无法判定枷锁顺序的时候的加时赛锁

     */

    private static final Object tieLock = new Object();

     

    public static void transferMoney2(final Account fromAccount, final Account toAccount, final int amount) throws InsufficientResourcesException

    {

        /**

         * 辅助内部类

         * @author xiaof

         *

         */

        class Helper

        {

            public void transfer() throws InsufficientResourcesException

            {

                //内部类可以随意访问外部类成员

                //按参数的顺序上锁,这个依据参数的调用方法的顺序

                if(fromAccount.getBalance() < amount)

                {

                    //账户余额不足,无法转账

                    throw new InsufficientResourcesException();

                }

                else

                {

                    fromAccount.debit(amount);

                    toAccount.credit(amount);

                }

            }

        }

        //返回给定对象的哈希码,该代码与默认的方法 hashCode() 返回的代码一样,无论给定对象的类是否重写 hashCode()

        int fromHash = System.identityHashCode(fromAccount);

        int toHash = System.identityHashCode(toAccount);

        //根据hash值判定加锁顺序,那么一样的对象的锁顺序就一定一样

        if(fromHash < toHash)

        {

            synchronized(fromAccount)

            {

                synchronized(toAccount)

                {

                    new Helper().transfer();

                }

            }

        }

        else if(toHash < fromHash)

        {

            synchronized(toAccount)

            {

                synchronized(fromAccount)

                {

                    new Helper().transfer();

                }

            }

        }

        else

        {

            //如果很不巧,hash值是一样的,那么就需要一个加时赛的机制,先获取外部锁,然后再此基础上对两个对象随机上锁

            synchronized(tieLock)

            {

                synchronized(fromAccount)

                {

                    synchronized(toAccount)

                    {

                        new Helper().transfer();

                    }

                }

            }

        }

         

    }

     

    static Account account1 = new Account(999);

    static Account account2 = new Account(999);

     

    public static void main(String[] args) throws InsufficientResourcesException {

        //对于第一个方法很容易死锁

        //比如:当有两个同时执行这个方法的调用时候

//        DeathLock dl = new DeathLock();

        //这个时候第一个调用在锁了account1,然后第二个调用锁了account2

        //同时第一个需要account2,第二个需要account1,这就发生竞争死锁了

//        dl.transferMoney(account1, account2, 998);

//        dl.transferMoney(account2, account1, 998);

//       

//        dl.transferMoney2(account1, account2, 998);

        ExecutorService pool = Executors.newFixedThreadPool(10);

        for(int i = 0; i < 5; ++ i)

        {

            pool.execute(new Runnable() {

                @Override

                public void run() {

                    try {

                        DeathLock.transferMoney2(account1, account2, 998);

                    } catch (InsufficientResourcesException e) {

                        e.printStackTrace();

                    }

                }

            });

        }

         

        for(int i = 0; i < 5; ++ i)

        {

            pool.execute(new Runnable() {

                @Override

                public void run() {

                    try {

                        DeathLock.transferMoney2(account2, account1, 998);

                    } catch (InsufficientResourcesException e) {

                        e.printStackTrace();

                    }

                }

            });

        }

         

        pool.shutdown();

    }

}

로그인 후 복사

테스트 결과:

[JAVA 동시 프로그래밍 실습] Lock Sequence 교착상태

관련 라벨:
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿