Java 中lock和synchronized关键词的区别

不同:


synchronized获得锁和释放的方式都是在 块结构中,当获取多个锁的时候必须以相反的顺序释放,并且是 自动解锁

Lock是JDK1.5以后引进的,它相比synchronized关键词要更 灵活,可用范围更 广泛

用法:


我们来看一个计数器的例子来比较这两者的不同:

1. synchronized
1
2
3
4
5
6
7
8
9
10
11
public class Counter {
 
   private int count = 0 ;
 
   public int inc() {
       synchronized ( this ) {
            return ++count;
      }
    }
}

//加了synchronized关键词后,count每次在块中只能被同一个进程加数。
//我们再来看下使用 Lock是如何实现的

2. Lock

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Counter {
 
   private Lock lock = new Lock();
  private int count = 0 ;
 
   public int inc() {
       lock.lock();
         int newCount = ++count;
      lock.unlock();
       return newCount;
     }
}

//从调用Lock方法之后lock的实例就被锁定,直道被调用unlock才解锁。

性能比较:

下面是在我电脑上跑出的结果:


Threads1x
synch
1x
Lock
1x
AtomicInteger
2x
synch
2x
Lock
2x
AtomicInteger
11.7972.1750.9473.2464.1111.703
28.6854.1341.88913.1444.9011.949
47.9423.0401.73513.1824.9601.945
87.6483.0111.89413.2874.9791.951
168.0172.9741.73513.0404.5731.950
327.9082.9581.77713.0594.8451.958
647.8532.9721.87813.3165.0041.954

从结果上看, 当线程数越多时Lock的效率越高

synchronized和Lock应该用哪一个,Sun没有官方的说法,也没有deprecate synchronized.从程序控制角度来说,我觉得哪个方便用哪个就可以了。

下面是测试代码,大家也可以自己跑一下:
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
  * Copyright (c) 2011.  By Peter Lawrey
  *
  */
package com.javasleep.threads;
 
import org.junit.Test;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
 
public class SynchronizedVsLockTest {
     static final Object mutex1 = new Object();
   static final Object mutex2 = new Object();
   static final Lock lock1 = new ReentrantLock();
   static final Lock lock2 = new ReentrantLock();
   static int counter1 = 0 ;
     static int counter2 = 0 ;
     static final AtomicInteger counter3 = new AtomicInteger();
   static final AtomicInteger counter4 = new AtomicInteger();
   public static final int LOOPS = 50 * 1000 * 1000 ;
    static final Map<integer, double []= "" > results = new TreeMap<integer, double []= "" >();
 
    @Test
    public void testSvL() throws InterruptedException {
      testSvL1();
      testSvL2();
 
      for (Map.Entry<integer, double []= "" > entry : results.entrySet()) {
           System.out.print( "" );
            System.out.print(entry.getKey());
            for ( double v : entry.getValue()) {
              System.out.print( "" );
                System.out.printf( "%.3f" , v);
            }
            System.out.println( "" );
      }
    }
 
    static void testSvL1() throws InterruptedException {
         for ( final int t : new int [] { 1 , 2 , 4 , 8 , 16 , 32 , 64 }) {
           doTest(t, 0 , new Runnable() {
                @Override
                public void run() {
                  for ( int i = 0 ; i < LOOPS / t; i++) {
                         synchronized (mutex1) {
                          counter1++;
                      }
                    }
                }
 
                @Override
                public String toString() {
                   return "1x synchronized {}" ;
                 }
            });
          doTest(t, 1 , new Runnable() {
                @Override
                public void run() {
                  for ( int i = 0 ; i < LOOPS / t; i++) {
                         lock1.lock();
                        try {
                            counter1++;
                      } finally {
                          lock1.unlock();
                      }
                    }
                }
 
                @Override
                public String toString() {
                   return "1x Lock.lock()/unlock()" ;
                }
            });
          doTest(t, 2 , new Runnable() {
                @Override
                public void run() {
                  for ( int i = 0 ; i < LOOPS / t; i++) {
                         counter3.getAndIncrement();
                  }
                }
 
                @Override
                public String toString() {
                   return "1x AtomicInteger" ;
               }
            });
      }
    }
 
    static void testSvL2() throws InterruptedException {
         for ( final int t : new int [] { 1 , 2 , 4 , 8 , 16 , 32 , 64 }) {
           doTest(t, 3 , new Runnable() {
                @Override
                public void run() {
                  for ( int i = 0 ; i < LOOPS / t; i++) {
                         synchronized (mutex1) {
                          counter1++;
                      }
                        synchronized (mutex2) {
                          counter2++;
                      }
                    }
                }
 
                @Override
                public String toString() {
                   return "2x synchronized {}" ;
                 }
            });
          doTest(t, 4 , new Runnable() {
                @Override
                public void run() {
                  for ( int i = 0 ; i < LOOPS / t; i++) {
                         lock1.lock();
                        try {
                            counter1++;
                      } finally {
                          lock1.unlock();
                      }
                        lock2.lock();
                        try {
                            counter2++;
                      } finally {
                          lock2.unlock();
                      }
                    }
                }
 
                @Override
                public String toString() {
                   return "2x Lock.lock()/unlock()" ;
                }
            });
          doTest(t, 5 , new Runnable() {
                @Override
                public void run() {
                  for ( int i = 0 ; i < LOOPS / t; i++) {
                         counter3.getAndIncrement();
                      counter4.getAndIncrement();
                  }
                }
 
                @Override
                public String toString() {
                   return "2x AtomicInteger" ;
               }
            });
      }
    }
 
    private static void doTest( int threads, int testNum, Runnable runnable)
          throws InterruptedException {
        ExecutorService es = Executors.newFixedThreadPool(threads);
      long start = System.nanoTime();
      try {
            for ( int i = 0 ; i < threads; i++)
                 es
                       .execute(runnable.getClass().getDeclaredConstructor(
                                 int . class ).newInstance(threads));
 
        } catch (Exception e) {
          throw new AssertionError(e);
         } finally {
          es.shutdown();
       }
        es.awaitTermination( 1 , TimeUnit.MINUTES);
        long time = (System.nanoTime() - start) / 1000000 ;
       System.out.printf( "%s with %d threads took %.3f seconds%n" , runnable
                 .toString(), threads, time / 1e3);
       double [] times = results.get(threads);
       if (times == null )
           results.put(threads, times = new double [ 6 ]);
         times[testNum] = time / 1e3;
     }
}


转载自: http://www.javasleep.com/archive/lock_synchronized.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值