利用while循环,不断尝试,而不是放弃cpu执行权,
class My { private AtomicReference<Thread> atomicReference = new AtomicReference<>(); public void myLock() { Thread thread = Thread.currentThread(); while (!atomicReference.compareAndSet(null, thread)) { } } public void myUnlock() { Thread thread = Thread.currentThread(); atomicReference.compareAndSet(thread, null); } }读写锁 首先如果按之前的syn 和Lock来说的话,他们都是独占锁,就是读写都只能有一个线程在操作,而java还有一种读可以有无数个线程操作,而写只能有一个线程写的读写锁。我们来看一下。
import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author Jing * @date 2020/10/4 0004 15:55 */ public class ReadWriteDemo { public static void main(String[] args) { Book book = new Book(); new Thread(() -> { for (int i = 0; i < 8; i++) { try { book.write(UUID.randomUUID().toString().substring(0,4)); } catch (InterruptedException e) { e.printStackTrace(); } } },"w1").start(); new Thread(() -> { for (int i = 0; i < 8; i++) { try { book.write(UUID.randomUUID().toString().substring(0,4)); } catch (InterruptedException e) { e.printStackTrace(); } } },"w2").start(); new Thread(() -> { for (int i = 0; i < 3; i++) { try { book.read(); } catch (InterruptedException e) { e.printStackTrace(); } } },"r1").start(); new Thread(() -> { for (int i = 0; i < 23; i++) { try { book.read(); } catch (InterruptedException e) { e.printStackTrace(); } } },"r2").start(); System.out.println(book.getList()); } } class Book{ private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final List<String> list = new ArrayList<>(10); public void read() throws InterruptedException { readWriteLock.readLock().lock(); System.out.println(Thread.currentThread().getName()+"准备读取数据....."); TimeUnit.MILLISECONDS.sleep(300); System.out.println("读取出来的数据为"+list.size()); System.out.println(Thread.currentThread().getName()+"读取完成"); readWriteLock.readLock().unlock(); } public void write(String s) throws InterruptedException { readWriteLock.writeLock().lock(); System.out.println(Thread.currentThread().getName()+"准备写入"); TimeUnit.MILLISECONDS.sleep(400); list.add(s+":"+Thread.currentThread().getName()); System.out.println(Thread.currentThread().getName()+"写入完成"); readWriteLock.writeLock().unlock(); } public List<String> getList(){ return list; } }如果运行完上面那个代码,可以发现如果有线程要写的话,一定是写完之后其他线程才可以读。而读却不这样,允许其他线程读或者写,这是因为读的时候他拷贝了一份当时的最新版,但不一定是最终的最新版。这有一些数据库隔离级别的不可重复读的味道。毕竟性能和数据一致性,从某些角度来看就是互相矛盾的。上述那些可行的方案都是权衡各种角度综合考虑下来的成熟解决方案。