在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突。冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突。按照我的理解在java中实现同步的方式分为三种,分别是:同步代码块机制,锁机制,信号量机制。


一、同步代码块

  在java的多线程并发开发过程中,我们最常用的方式就是使用同步代码关键字(synchronized)。这种方式的使用不是特别复杂,需要注意的只是你需要明确到底同步的是那个对象,只有当同步的对象一致的情况下,才能够控制互斥的操作。一般情况下,我们会同步this或者是当前class对象。同步this对当前实例有效,同步class对当前所有class的对象有效。下面这个demo的功能是,启动十个线程,最终结果是每个线程都将共享的变量加上1.

private static final java.util.Random random = new java.util.Random(System.currentTimeMillis());

public static void main(String[] args) {
    Runnable runnable = new Runnable() {
        private int count = 0; // 资源对象

        @Override
        public void run() {
            try {
                int oldCount = count;
                Thread.sleep(random.nextInt(1000) + 10); // 处理
                count = oldCount + 1;
                System.out.println(Thread.currentThread().getName() + ", 原有资源:" + oldCount + ", 现在预期资源:" + (oldCount + 1) + ",现在实际资源:" + count);
            } catch (InterruptedException e) {
            }
        }
    };

    for (int i = 0; i < 10; i++) {
        new Thread(runnable).start();
    }
}

  我们可以发现结果如下图所示,明显可以看出在是个线程访问一个变量的情况下,导致最终的结果不对。

[java多线程] - 锁机制&同步代码块&信号量

  加同步锁的代码和上述代码差不多,区别只是在获取资源和修改资源的时候进行同步块处理。

int oldCount = 0;
synchronized (this) {
    oldCount = count;
    Thread.sleep(random.nextInt(1000) + 10); // 处理
    count = oldCount + 1;
}

[java多线程] - 锁机制&同步代码块&信号量

二、锁机制

  在Java中的锁机制是通过java.util.concurrent.locks.Lock来实现的,这个接口主要有三个实现类,分别是ReentrantLock,ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock。锁机制和同步代码块相比,我们可以明显的发现使用lock机制会降低同步粒度,提高性能。特别是在一些情况下,使用lock是一种非常不错的选择,比如说在读远远高于写的状况下,使用读写锁那是一种非常不错的选择。下面直接来一个cachedemo

 1 static class CacheDemo {
 2         private static final int maxSize = 100000; // 最大存储量
 3         private static CacheDemo demo;
 4         private Map<String, String> cache = new LinkedHashMap<String, String>() {
 5             private static final long serialVersionUID = -7259602073057254864L;
 6 
 7             protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
 8                 return maxSize > this.size(); // 超过就移除
 9             };
10         };
11         private ReentrantReadWriteLock rrel = new ReentrantReadWriteLock();
12         private Lock writeLock = rrel.writeLock(); // 写锁
13         private Lock readLock = rrel.readLock(); // 读锁
14 
15         /**
16          * 获取cache对象
17          * 
18          * @return
19          */
20         public static CacheDemo instance() {
21             if (demo == null) {
22                 synchronized (CacheDemo.class) {
23                     if (demo == null) {
24                         demo = new CacheDemo();
25                     }
26                 }
27             }
28             return demo;
29         }
30 
31         /**
32          * 添加
33          * 
34          * @param key
35          * @param value
36          */
37         public void put(String key, String value) {
38             this.writeLock.lock(); // 加锁
39             try {
40                 this.cache.put(key, value);
41             } finally {
42                 // 防止在操作过程中出现异常,使用try-finally保证解锁一定执行。
43                 this.writeLock.unlock(); // 解锁
44             }
45         }
46 
47         /**
48          * 获取这个对象
49          * 
50          * @param key
51          * @return
52          */
53         public String get(String key) {
54             this.readLock.lock(); // 加锁
55             try {
56                 return this.cache.get(key);
57             } finally {
58                 this.readLock.unlock(); // 解锁
59             }
60         }
61 
62         /**
63          * 移除key
64          * 
65          * @param key
66          */
67         public void remove(String key) {
68             this.writeLock.lock();
69             try {
70                 this.cache.remove(key);
71             } finally {
72                 this.writeLock.unlock();
73             }
74         }
75 
76         /**
77          * 清空
78          */
79         public void clean() {
80             this.writeLock.lock();
81             try {
82                 this.cache.clear();
83             } finally {
84                 this.writeLock.unlock();
85             }
86         }
87     }
CacheDemo

相关文章: