The previous article covered reentrant locking and the corresponding conditional operations, as described in The Multithreaded Basics of JAVA Concurrency (2). In this article we continue to talk about the concurrency classes included in the JDK.
Semaphore
For most locks, threads are mutually exclusive, allowing only one thread to enter a critical section. But the semaphore here allows multiple threads to enter the critical section. It can be viewed broadly as a shared lock.
acquire()
This is to take a semaphore so that the thread can enter the critical section.
public void acquire(a) throws InterruptedException {
sync.acquireSharedInterruptibly(1);// To get a semaphore license
}
Copy the code
A thread can also take more than one semaphore.
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);// Get multiple semaphore permissions
}
Copy the code
release()
The method is to release the semaphore of the current thread.
public void release(a) {
sync.releaseShared(1);
}
Copy the code
tryAcquire()
It’s trying to get a semaphore, failing that, doing something else.
public boolean tryAcquire(a) {
return sync.nonfairTryAcquireShared(1) > =0;
}
Copy the code
It also has a way of trying to get semaphores based on time:
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
}
Copy the code
Of course, there are also fair and unfair signals in the semaphore itself, and AQS are also used in it. The main core of the concurrent operation class in the JDK is AQS. Here’s a little Demo to show you how it works.
package com.montos.lock;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/** ** Semaphore **@authorMontos * * May 30, 2019 * */
public class SemaphoreDemo implements Runnable {
final Semaphore semaphore = new Semaphore(5);
@Override
public void run(a) {
try {
semaphore.acquire();
Thread.sleep(2000);
System.out.println(Thread.currentThread().getId() + " thread is done");
} catch (InterruptedException e) {
e.printStackTrace();
} finally{ semaphore.release(); }}public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(20);
final SemaphoreDemo demo = new SemaphoreDemo();
for (int i = 0; i < 20; i++) { exec.submit(demo); }}}Copy the code
ReadWriteLock
Read/write locks are used to increase thread efficiency. The lock introduced above will enter the corresponding lock holding stage whether it is read or write, and this time the read and write lock is a good embodiment of its role. It divides functions so that reads and writes are separated.
The association between read locks and write locks:
read | write | |
---|---|---|
read | non-blocking | blocking |
write | blocking | blocking |
Take a look at the next small demo:
package com.montos.lock;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadLockDemo {
public static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public static void main(String[] args) {
// Read and write simultaneously
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new Runnable() {
@Override
public void run(a) { readFile(Thread.currentThread()); }}); service.execute(new Runnable() {
@Override
public void run(a) { writeFile(Thread.currentThread()); }}); }/ / read operation
public static void readFile(Thread thread) {
lock.readLock().lock();
boolean readLock = lock.isWriteLocked();
if(! readLock) { System.out.println("Currently a read lock!");
}
try {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(thread.getName() + ": Reading operation in progress......");
}
System.out.println(thread.getName() + ": Read operation complete!");
} finally {
System.out.println("Release read lock!"); lock.readLock().unlock(); }}/ / write operations
public static void writeFile(Thread thread) {
lock.writeLock().lock();
boolean writeLock = lock.isWriteLocked();
if (writeLock) {
System.out.println("Currently write lock!");
}
try {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(thread.getName() + ": Write operation in progress......");
}
System.out.println(thread.getName() + ": Write operation complete!");
} finally {
System.out.println("Release write lock!"); lock.writeLock().unlock(); }}}Copy the code
The above is the introduction of the JDK in the operation of two locks and their characteristics, the specific use of business or depends on the specific requirements, consider whether it is necessary to use.