Java 并发(JUC 包-01)

mac2024-01-28  30

>JUC ? 就是Java API 中这三个包的简称:

>atomic 包

CAS:compare and swap ?要实现原子性操作

这是一种原子性操作,这是一种原子性赋值,

比如原来的 ++i ,现在对 i 进行原子性加一,从Java5之后就有了这个原子性操作,主要借助unsafe类(源码无法查看),Java为我们封装了一些类:

在atomic 包中

之前的例子改一下:

public class TestAtomic { V v = new V(); public static void main(String[] args) { TestAtomic ta = new TestAtomic(); ta.go(); } private void go() { for (int i = 0; i < 3; i++) { new Thread(new Runnable() { public void run() { for (int j = 0; j < 10000; j++) { v.add(); } } }).start(); } while (Thread.activeCount() > 1) { } System.out.println(v.ai.get()); } class V { //public int i = 0; public AtomicInteger ai=new AtomicInteger(); public void add() {//原本在这个地方加个锁,将整个方法锁住了,悲观锁(重量级锁) //如果i++ 变成原子性的就没必要在外部加锁了 //i++; ai.getAndIncrement(); } } }

>locks 包

1.重入锁基本使用:

public class TestLock { public static void main(String[] args) { new TestLock().go(); } public void go() { V v = new V(); new Thread(new Runnable() { public void run() { while (true) { v.printString("AAAAAAAAAAAAAA"); } } }).start(); new Thread(new Runnable() { public void run() { while (true) { v.printString("BBBBBBBBBBBBBB"); } } }).start(); } class V { // 使用Lock 代替 synchronized ReentrantLock lock = new ReentrantLock(); public void printString(String str) { try { lock.lock(); for (int i = 0; i < str.length(); i++) { System.out.print(str.charAt(i)); } System.out.println(); } catch (Exception e) { } finally { // 为了确保锁可以被释放掉 lock.unlock(); } } } }

2.条件锁:使用条件锁实现线程轮询

public class TestConditionLock { V v = new V(); public static void main(String[] args) { TestConditionLock t = new TestConditionLock(); t.go(); } private void go() { new Thread(new Runnable() { @Override public void run() { while (true) { v.f1(); } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { v.f2(); } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { v.f3(); } } }).start(); } class V { Lock lock = new ReentrantLock(); Condition condition1 = lock.newCondition(); Condition condition2 = lock.newCondition(); Condition condition3 = lock.newCondition(); int token = 1; public void f1() { lock.lock(); try { while (token != 1) { try { condition1.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } token = 2; System.out.println(Thread.currentThread().getName() + "--f1"); condition2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void f2() { lock.lock(); try { while (token != 2) { try { condition2.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } token = 3; System.out.println(Thread.currentThread().getName() + "--f2"); condition3.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void f3() { lock.lock(); try { while (token != 3) { try { condition3.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } token = 1; System.out.println(Thread.currentThread().getName() + "--f3"); condition1.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } }

3.读写锁:

读写锁分为读锁和写锁。多个读锁之间不互斥、读锁和写锁之间互斥、写锁和写锁之间互斥。这一功能很重要,对并发读取提高了性能。

读写锁使用到了JUC中的ReentrantReadWriteLock类:

/** * 测试读写锁: 1.有个地方存东西 2.提供读和写两个方法,对这两个地方进行操作 3.开启多个线程,有读,有写 4.证明读的时候可以读,写的时候不能其他操作 */ public class TestReentrantReadWriteLock { public static void main(String[] args) { TestReentrantReadWriteLock t = new TestReentrantReadWriteLock(); t.go(); } Data d = new Data(); Random r = new Random(); private void go() { for (int i = 0; i < 3; i++) { new Thread(new Runnable() { @Override public void run() { d.write(r.nextInt(1000)); } }).start(); } for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { d.read(r.nextInt(999)); } }).start(); } } class Data { List<Integer> list = new ArrayList<>(); { for (int i = 0; i < 1000; i++) { list.add(i); } } // 创建读写锁 ReadWriteLock lock = new ReentrantReadWriteLock(); Lock readLock = lock.readLock(); Lock writeLock = lock.writeLock(); public void read(int index) { readLock.lock(); try { System.out.println(Thread.currentThread().getName() + "进入读方法"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } int i = list.get(index); System.out.println(Thread.currentThread().getName() + "读到数据" + i); System.out.println(Thread.currentThread().getName() + "读取完毕"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { readLock.unlock(); } } public void write(int data) { writeLock.lock(); try { System.out.println(Thread.currentThread().getName() + "进入写方法"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } list.add(data); System.out.println(Thread.currentThread().getName() + "写入完毕"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { writeLock.unlock(); } } } }

显示:

Thread-0进入写方法 Thread-0写入完毕 Thread-1进入写方法 Thread-1写入完毕 Thread-2进入写方法 Thread-2写入完毕 Thread-3进入读方法 Thread-4进入读方法 Thread-5进入读方法 Thread-6进入读方法 Thread-7进入读方法 Thread-4读到数据403 Thread-5读到数据276 Thread-5读取完毕 Thread-7读到数据98 Thread-7读取完毕 Thread-6读到数据628 Thread-6读取完毕 Thread-3读到数据258 Thread-3读取完毕 Thread-4读取完毕

数据库中有表级别锁,行级锁,如何实现?思考。

单例模式中的同步代码块如何取代:

先看API实例:

class CachedData { Object data; volatile boolean cacheValid; final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock(); rwl.writeLock().lock(); try { // Recheck state because another thread might have // acquired write lock and changed state before we did. if (!cacheValid) { data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.readLock().lock(); } finally { rwl.writeLock().unlock(); // Unlock write, still hold read } } try { use(data); } finally { rwl.readLock().unlock(); } } }

改造一下单例:

public class Book { private static Book instance = null; private static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); public static Book getInstance() { try { rwl.readLock().lock(); if (instance == null) { rwl.readLock().unlock(); rwl.writeLock().lock(); if (instance == null) { instance = new Book(); } rwl.readLock().lock(); rwl.writeLock().unlock(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { rwl.readLock().unlock(); } return instance; } }

 

最新回复(0)