zoukankan      html  css  js  c++  java
  • Java多线程 ReadWriteLock、StampedLock用法

    无论是synchronized机制,还是ReentrantLock加锁,实际上只有一个线程可以执行临界区代码。即读写、写读、读读、写写 两个线程之间是相互阻塞的。然而读线程之间是需要并发的,Java使用ReadWriteLock实现多个线程同时读提高并发性能。

    1、ReadWriteLock

    import java.util.Arrays;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    public class RWLock {
        public static void main(String[] args) {
            var point = new Pixel();
            Thread t1 = new Thread() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        point.move(i, i);
                    }
                }
            };
            t1.start();
    
            for (int j = 0; j < 10; j++) {
                Thread t = new Thread() {
                    @Override
                    public void run() {
                        point.getPosition();
                    }
                };
                t.start();
            }
        }
    }
    
    class Pixel {
        private int[] position = { 0, 0 };
        private final ReadWriteLock lock = new ReentrantReadWriteLock();
        private final Lock writeLock = lock.writeLock();
        private final Lock readLock = lock.readLock();
    
        public void move(int i, int j) {
            writeLock.lock();
            try {
                this.position[0] = i;
                this.position[1] = j;
            } finally {
                writeLock.unlock();
            }
        }
    
        public void getPosition() {
            readLock.lock();
            try {
                System.out.println(Arrays.toString(this.position));
    
            } finally {
                readLock.unlock();
            }
        }
    }

    ReadWriteLock 的用法:在需要加写锁的地方调用  writeLock.lock(); 在需要加读锁的地方调用 readLock.lock();

    ReadWriteLock保证多个线程可以同时获取读锁,但读写,写读,写写线程之间仍然是阻塞的。

    2、StampedLock

    由于ReadWriteLock在读的过程中不允许写,这是一种悲观的读锁,Java 8引入了新的读写锁 StampedLock,允许读的过程中写入,这是一种乐观的读锁。

    class Point {
        private final StampedLock stampedLock = new StampedLock();
    
        private double x;
        private double y;
    
        public void move(double x1, double y1) {
            long stamp = stampedLock.writeLock();
            try {
                this.x += x1;
                this.y += y1;
            } finally {
                stampedLock.unlock(stamp);
            }
        }
    
        public double getDistance() {
            long stamp = stampedLock.tryOptimisticRead();
            double x2 = this.x;
            double y2 = this.y;
            if (stampedLock.validate(stamp)) {
                stamp = stampedLock.readLock();
                try {
                    x2 = this.x;
                    y2 = this.y;
                } finally {
                    stampedLock.unlock(stamp);
                }
            }
            return Math.sqrt(x2 * x2 + y2 * y2);
        }
    }

    需要注意的是:

    1、StampedLock 获取锁的方法会返回一个邮戳(Stamp);

    2、释放锁的方法也需要一个邮戳(Stamp);

    3、StampedLock是不可重入的;

    4、StampedLock有三种访问模式:

    • Reading(读模式):功能和ReentrantReadWriteLock的读锁类似
    • Writing(写模式):功能和ReentrantReadWriteLock的写锁类似
    • Optimistic reading(乐观读模式):这是一种优化的读模式。

    5、StampedLock支持读锁和写锁的相互转换;

    6、无论写锁还是读锁,都不支持Conditon等待。

    参考链接:

    https://segmentfault.com/a/1190000015808032

    https://www.liaoxuefeng.com/wiki/1252599548343744/1309138673991714

  • 相关阅读:
    uTenux-OS-Task再探
    uTenux——LED驱动讲解
    uTenux——HelloWord
    uTenux——重新整理底层驱动库
    template的超级bug
    [LeetCode] Integer to Roman
    [LeetCode] Roman to Integer
    [LeetCode]Flatten Binary Tree to Linked List
    [LeetCode] LRU Cache [Forward]
    [LeetCode] Reorder List
  • 原文地址:https://www.cnblogs.com/engeng/p/15559949.html
Copyright © 2011-2022 走看看