diff --git a/week_03/57/AQS-057.txt b/week_03/57/AQS-057.txt new file mode 100644 index 0000000000000000000000000000000000000000..e435db242e314e9f78ade7cf6c1d9933774805a7 --- /dev/null +++ b/week_03/57/AQS-057.txt @@ -0,0 +1,136 @@ +1.为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁定和相关同步器(信号量、事件,等等)提供一个框架。 +此类的设计目标是成为依靠单个原子 int 值来表示状态的大多数同步器的一个有用基础。 +子类必须定义更改此状态的受保护方法,并定义哪种状态对于此对象意味着被获取或被释放。 +假定这些条件之后,此类中的其他方法就可以实现所有排队和阻塞机制。 +子类可以维护其他状态字段, +但只是为了获得同步而只追踪使用 getState()、setState(int) 和 +compareAndSetState(int, int) 方法来操作以原子方式更新的 int 值。 + + +2.protected final int getState() { + return state; + } + + 返回同步状态的当前值。此操作具有 volatile 读的内存语义。 + + 返回: + 当前状态值 + protected final void setState(int newState) { + state = newState; + } + +3.protected final boolean compareAndSetState(int expect, int update) { + // See below for intrinsics setup to support this + return unsafe.compareAndSwapInt(this, stateOffset, expect, update); + } + + + 如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。此操作具有 volatile 读和写的内存语义。 + +4.protected boolean tryAcquire(int arg) { + throw new UnsupportedOperationException(); + } + 试图在独占模式下获取对象状态。此方法应该查询是否允许它在独占模式下获取对象状态,如果允许,则获取它。 +此方法总是由执行 acquire 的线程来调用。如果此方法报告失败, +则 acquire 方法可以将线程加入队列(如果还没有将它加入队列), +直到获得其他某个线程释放了该线程的信号。可以用此方法来实现 Lock.tryLock() 方法。 + +5. protected boolean tryRelease(int arg) { + throw new UnsupportedOperationException(); + } + 试图在共享模式下获取对象状态。此方法应该查询是否允许它在共享模式下获取对象状态,如果允许,则获取它。 +此方法总是由执行 acquire 线程来调用。如果此方法报告失败,则 acquire 方法可以将线程加入队列(如果还没有将它加入队列), +直到获得其他某个线程释放了该线程的信号。 + +6.protected boolean tryReleaseShared(int arg) { + throw new UnsupportedOperationException(); + } + 试图设置状态来反映共享模式下的一个释放。 +此方法总是由正在执行释放的线程调用。 + +7.protected boolean isHeldExclusively() { + throw new UnsupportedOperationException(); + } + 如果对于当前(正调用的)线程,同步是以独占方式进行的,则返回 true。 + 此方法是在每次调用非等待 AbstractQueuedSynchronizer.ConditionObject 方法时调用的。(等待方法则调用 release(int)。) + +8. public final void acquire(int arg) { + if (!tryAcquire(arg) && + acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) + selfInterrupt(); + } +以独占模式获取对象,忽略中断。通过至少调用一次 tryAcquire(int) 来实现此方法,并在成功时返回。 +否则在成功之前,一直调用 tryAcquire(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。 +可以使用此方法来实现 Lock.lock() 方法 + +9.public final void acquireInterruptibly(int arg) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + if (!tryAcquire(arg)) + doAcquireInterruptibly(arg); + } + 以独占模式获取对象,如果被中断则中止。通过先检查中断状态,然后至少调用一次 tryAcquire(int) 来实现此方法, + 并在成功时返回。否则在成功之前,或者线程被中断之前,一直调用 tryAcquire(int) 将线程加入队列, + 线程可能重复被阻塞或不被阻塞。可以使用此方法来实现 Lock.lockInterruptibly() 方法。 + +10. public final boolean tryAcquireNanos(int arg, long nanosTimeout) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + return tryAcquire(arg) || + doAcquireNanos(arg, nanosTimeout); + }试图以独占模式获取对象,如果被中断则中止,如果到了给定超时时间,则会失败。 + 通过先检查中断状态,然后至少调用一次 tryAcquire(int) 来实现此方法,并在成功时返回。 + 否则,在成功之前、线程被中断之前或者到达超时时间之前,一直调用 tryAcquire(int) 将线程加入队列, + 线程可能重复被阻塞或不被阻塞。可以用此方法来实现 Lock.tryLock(long, TimeUnit) 方法。 + +11.public final boolean release(int arg) { + if (tryRelease(arg)) { + Node h = head; + if (h != null && h.waitStatus != 0) + unparkSuccessor(h); + return true; + } + return false; + } + 以独占模式释放对象。如果 tryRelease(int) 返回 true,则通过消除一个或多个线程的阻塞来实现此方法。 + 可以使用此方法来实现 Lock.unlock() 方法 + +12.public final void acquireShared(int arg) { + if (tryAcquireShared(arg) < 0) + doAcquireShared(arg); + } + 以共享模式获取对象,忽略中断。通过至少先调用一次 tryAcquireShared(int) 来实现此方法, + 并在成功时返回。否则在成功之前,一直调用 tryAcquireShared(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。 + +13.public final void acquireSharedInterruptibly(int arg) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + if (tryAcquireShared(arg) < 0) + doAcquireSharedInterruptibly(arg); + } +以共享模式获取对象,如果被中断则中止。通过先检查中断状态,然后至少调用一次 tryAcquireShared(int) 来实现此方法, +并在成功时返回。否则在成功或线程被中断之前,一直调用 tryAcquireShared(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。 + +14.public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + return tryAcquireShared(arg) >= 0 || + doAcquireSharedNanos(arg, nanosTimeout); + } +试图以共享模式获取对象,如果被中断则中止,如果到了给定超时时间,则会失败。 +通过先检查中断状态,然后至少调用一次 tryAcquireShared(int) 来实现此方法,并在成功时返回。 +否则在成功之前、线程被中断之前或者到达超时时间之前,一直调用 tryAcquireShared(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。 + +15.public final boolean releaseShared(int arg) { + if (tryReleaseShared(arg)) { + doReleaseShared(); + return true; + } + return false; + } + 以共享模式释放对象。如果 tryReleaseShared(int) 返回 true,则通过消除一个或多个线程的阻塞来实现该方法。 + diff --git "a/week_03/57/Java\345\206\205\345\255\230\346\250\241\345\236\213-057.docx" "b/week_03/57/Java\345\206\205\345\255\230\346\250\241\345\236\213-057.docx" new file mode 100644 index 0000000000000000000000000000000000000000..96e1281a79f9d94d3d44d805d26d9730da20102f Binary files /dev/null and "b/week_03/57/Java\345\206\205\345\255\230\346\250\241\345\236\213-057.docx" differ diff --git a/week_03/57/ReentrantLock-057.txt b/week_03/57/ReentrantLock-057.txt new file mode 100644 index 0000000000000000000000000000000000000000..707fdef610fc4b3bc0d2af8a1c069bf7c3fcf160 --- /dev/null +++ b/week_03/57/ReentrantLock-057.txt @@ -0,0 +1,45 @@ +1.使用了内部类Sync继承自AQS +abstract static class Sync extends AbstractQueuedSynchronizer {} + +2.默认创建非公平锁 +public ReentrantLock() { + sync = new NonfairSync(); + } +3.可以根据传入的参数确定创建 公平/非公平锁 +public ReentrantLock(boolean fair) { + sync = fair ? new FairSync() : new NonfairSync(); + } + +4.常见用法 +class X { + * private final ReentrantLock lock = new ReentrantLock(); + * // ... + * + * public void m() { + * lock.lock(); // block until condition holds + * try { + * // ... method body + * } finally { + * lock.unlock() + * } + * } + * }} + +5.阻塞和非阻塞获得锁方式 +阻塞public void lock() { + sync.lock(); + } + +非阻塞public boolean tryLock() { + return sync.nonfairTryAcquire(1); + } + +非阻塞并且带有超时时间public boolean tryLock(long timeout, TimeUnit unit) + throws InterruptedException { + return sync.tryAcquireNanos(1, unit.toNanos(timeout)); + } + +6.释放锁 +public void unlock() { + sync.release(1); + } \ No newline at end of file diff --git a/week_03/57/Semaphore-057.txt b/week_03/57/Semaphore-057.txt new file mode 100644 index 0000000000000000000000000000000000000000..3b981772bd0710f16355b4391b894a279bea5517 --- /dev/null +++ b/week_03/57/Semaphore-057.txt @@ -0,0 +1,99 @@ +1.使用了内部类Sync继承自AQS +abstract static class Sync extends AbstractQueuedSynchronizer {} + +2.公平和非公平版本 +/** + * NonFair version + */ + static final class NonfairSync extends Sync { + private static final long serialVersionUID = -2694183684443567898L; + + NonfairSync(int permits) { + super(permits); + } + + protected int tryAcquireShared(int acquires) { + return nonfairTryAcquireShared(acquires); + } + } + + /** + * Fair version + */ + static final class FairSync extends Sync { + private static final long serialVersionUID = 2014338818796000944L; + + FairSync(int permits) { + super(permits); + } + + protected int tryAcquireShared(int acquires) { + for (;;) { + if (hasQueuedPredecessors()) + return -1; + int available = getState(); + int remaining = available - acquires; + if (remaining < 0 || + compareAndSetState(available, remaining)) + return remaining; + } + } + } + +3.构造方法 + 1.传入一个int类型许可 + public Semaphore(int permits) { + sync = new NonfairSync(permits); + } + 2.传入许可和是否公平的参数 + public Semaphore(int permits, boolean fair) { + sync = fair ? new FairSync(permits) : new NonfairSync(permits); + } + +4.获得方法 + 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。 + public void acquire() throws InterruptedException { + sync.acquireSharedInterruptibly(1); + } + 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,否则线程是已中断的。 + public void acquire(int permits) throws InterruptedException { + if (permits < 0) throw new IllegalArgumentException(); + sync.acquireSharedInterruptibly(permits); + } + + 从此信号量中获取许可,在有可用的许可前将其阻塞。 + public void acquireUninterruptibly() { + sync.acquireShared(1); + } + 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。 + public void acquireUninterruptibly(int permits) { + if (permits < 0) throw new IllegalArgumentException(); + sync.acquireShared(permits); + } + 非阻塞 + 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。 + public boolean tryAcquire() { + return sync.nonfairTryAcquireShared(1) >= 0; + } + 仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。 + public boolean tryAcquire(int permits) { + if (permits < 0) throw new IllegalArgumentException(); + return sync.nonfairTryAcquireShared(permits) >= 0; + } + 如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。 + public boolean tryAcquire(int permits, long timeout, TimeUnit unit) + throws InterruptedException { + if (permits < 0) throw new IllegalArgumentException(); + return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout)); + } + +5.释放方法 + 释放一个许可,将其返回给信号量。 + public void release() { + sync.releaseShared(1); + } + 释放给定数目的许可,将其返回到信号量。 + public void release(int permits) { + if (permits < 0) throw new IllegalArgumentException(); + sync.releaseShared(permits); + } \ No newline at end of file diff --git a/week_03/57/synchronized-057.txt b/week_03/57/synchronized-057.txt new file mode 100644 index 0000000000000000000000000000000000000000..9d2486c3d01449766737213f73eb54f454cdf91f --- /dev/null +++ b/week_03/57/synchronized-057.txt @@ -0,0 +1,9 @@ +1.synchronized:jvm关键字 +monitorenter,底层是通过monitor对象来完成,其实wait/notify等方法也依赖于monitor对象只有在同 +步或方法中才能掉wait/notify等方法 + +2.sychronized不需要用户取手动释放锁,当synchronized代码执行完后系统会自动让线程释放对锁的占用 + +3.synchronized不可中断,除非抛出异常或者正常运行完成 + +4.为非公平锁 \ No newline at end of file diff --git a/week_03/57/volatile-057.txt b/week_03/57/volatile-057.txt new file mode 100644 index 0000000000000000000000000000000000000000..a15ce1c1657acaa6c1e9de7af79d9ae0519bd115 --- /dev/null +++ b/week_03/57/volatile-057.txt @@ -0,0 +1,7 @@ +1.volatile时java虚拟机提供的轻量级同步机制 +三个特点: + 1.保证可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改的值 + 2.不保证原子性:原子性:不可分割、完整性,即某个线程正在做某个具体业务时,中间不可以被加塞或者被分割,需要整体完 + 整,要么同时成功,要么同时失败 + 3.禁止指令重排:多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性时无法确定 + 的,结果无法预测 \ No newline at end of file diff --git "a/week_03/57/\345\210\206\345\270\203\345\274\217\351\224\201-057.txt" "b/week_03/57/\345\210\206\345\270\203\345\274\217\351\224\201-057.txt" new file mode 100644 index 0000000000000000000000000000000000000000..079736e06f0c799e27c65c183f4b34f5f1d55984 --- /dev/null +++ "b/week_03/57/\345\210\206\345\270\203\345\274\217\351\224\201-057.txt" @@ -0,0 +1,14 @@ + + +特点: + 互斥性:和我们本地锁一样互斥性是最基本,但是分布式锁需要保证在不同节点的不同线程的互斥。 + 可重入性:同一个节点上的同一个线程如果获取了锁之后那么也可以再次获取这个锁。 + 锁超时:和本地锁一样支持锁超时,防止死锁。 + 高效,高可用:加锁和解锁需要高效,同时也需要保证高可用防止分布式锁失效,可以增加降级。 + 支持阻塞和非阻塞:和ReentrantLock一样支持lock和trylock以及tryLock(long timeOut)。 + 支持公平锁和非公平锁(可选):公平锁的意思是按照请求加锁的顺序获得锁,非公平锁就相反是无序的。这个一般来说实现的比较少。 + +几种实现方式: + 1.MySql + 2.Zk + 3.Redis \ No newline at end of file