同步:保证共享数据在同一时刻只被一个(使用信号量的时候可以是多个)线程使用
互斥:互斥是实现同步的手段,同步是互斥要实现的目的
*** 作系统层面的概念:
- 临界区
- 互斥量
- 信号量
- synchronized关键字经过编译后会在代码块(同步块)的前后形成monitorenter、monitorexit两个字节码指令,这两个字节码都需要一个reference类型的参数来指明要锁定和解锁的对象;
- 执行monitorenter,如果获取到对象的锁或者当前线程已经持有锁,锁计数器+1
- 如果获取对象锁失败,线程阻塞等待,直到其他线程执行monitorexit指令,释放锁资源
- 阻塞或唤醒一个线程,都需要 *** 作系统从用户态转换为核心态,会消耗很多系统资源,所以synchronized是重量级锁
- 执行monitorexit 锁计数器 -1
下面描述来自 https://www.hollischuang.com/archives/1883
- 方法级的同步是隐式的,运行时常量池中会有一个ACC_SYNCHRONIZED标志。
- 当某个线程要访问某个方法的时候,会检查是否有ACC_SYNCHRONIZED,
- 如果有设置ACC_SYNCHRONIZED标志,需要先获取锁,然后开始执行方法,方法执行之后再释放锁。
- 这时如果其他线程来请求执行方法,会因为无法获得锁而被阻塞。
- 如果在方法执行过程中,发生了异常,并且方法内部并没有处理该异常,那么在异常被抛到方法外面之前锁会被自动释放。
https://blog.csdn.net/hduzjn/article/details/121420595
package java.util.concurrent.locks
package java.util.concurrent.locks; import java.util.concurrent.TimeUnit; public interface Lock { // try void lock(); // finally void unlock(); // 获取锁的过程中可中断 synchronized不可以 void lockInterruptibly() throws InterruptedException; // Acquires the lock if it is available and returns immediately with the value true. // If the lock is not available then this method will return immediately with the value false // This usage ensures that the lock is unlocked if it was acquired, // and doesn't try to unlock if the lock was not acquired. // Returns : true if the lock was acquired and false otherwise // boolean tryLock(); // 根据传入的时间段获取锁,在指定时间内没有获取锁则返回false, // 如果在指定时间内当前线程未被中并断获取到锁则返回true boolean tryLock(long time, TimeUnit unit) throws InterruptedException; Condition newCondition(); }2.2 Condition 接口
Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.
- 替代同步方法和状态,以及监视器方法 synchronized/wait/notify/notifyAll
- await 释放锁
- signal 获取锁
A Condition instance is intrinsically bound to a lock. To obtain a Condition instance for a particular Lock instance use its newCondition() method.
- Condition和锁绑定,配合锁才能使用,通过 lock.newCondition() 获得Condition实例
public interface Condition { void await() throws InterruptedException; void awaitUninterruptibly(); long awaitNanos(long nanosTimeout) throws InterruptedException; boolean await(long time, TimeUnit unit) throws InterruptedException; boolean awaitUntil(Date deadline) throws InterruptedException; void signal(); void signalAll(); }2.2.1 使用例子
* class BoundedBuffer { * final Lock lock = new ReentrantLock(); * final Condition notFull = lock.newCondition(); * final Condition notEmpty = lock.newCondition(); * * final Object[] items = new Object[100]; * int putptr, takeptr, count; * * public void put(Object x) throws InterruptedException { * lock.lock(); * try { * while (count == items.length) * notFull.await(); * items[putptr] = x; * if (++putptr == items.length) putptr = 0; * ++count; * notEmpty.signal(); * } finally { * lock.unlock(); * } * } * * public Object take() throws InterruptedException { * lock.lock(); * try { * while (count == 0) * notEmpty.await(); * Object x = items[takeptr]; * if (++takeptr == items.length) takeptr = 0; * --count; * notFull.signal(); * return x; * } finally { * lock.unlock(); * } * } * } *2.2.2 ConditionObject Condition Queue
private static final long serialVersionUID = 1173984872572414699L; private transient Node firstWaiter; private transient Node lastWaiter;
https://www.cnblogs.com/zerotomax/p/8969416.html
https://blog.csdn.net/zy1994hyq/article/details/84562475
- 默认是非公平锁
调用内部的sync的方法
public void lock() { sync.lock(); } public boolean tryLock() { return sync.nonfairTryAcquire(1); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); }2.3.3 Sync / NoFairSync / FairSync ① Sync nonfairTryAcquire
- 可重入的逻辑
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); // 锁没被占用 CAS 获取锁 if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 判断获取锁的线程 是否是当前占用锁的线程 else if (current == getExclusiveOwnerThread()) { // 如果是 state =state + acquires // 可重入在此展现 int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }② NonfairSync 非公平锁
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; final void lock() { // 判断state是否是0(表示当前锁未被占用),如果是0则把它置为1,然后设置独占线程为当前线程 // 非公平的体现 ,占用锁的线程释放了锁,state状态变成0,此时如果有一个新来的线程正好调用lock方法, // 那么它会在 wait queue队列 中等待的线程 之前获得锁 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else // 否则执行 AQS 的 acquire方法 acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }③ FairSync 公平锁
static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; // 这里没有 if else判断 state的状态,然后获取锁 final void lock() { // 直接调用 acquire ,这样所有线程都要在 wait queue 里排队 acquire(1); } protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && // 如果是头节点、无锁状态,设置当前线程为独占线程 compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 这里和上边的 非公平锁重入一样 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)