ReentrantLock:
使用场景 |
说明 |
修饰方法 |
public synchronized void someMethod() { // 方法体 } |
修饰代码块 | public void someMethod() { synchronized (lockObject) { // 临界区代码 } } |
修饰静态方法 | public static synchronized void someStaticMethod() { // 方法体 } |
修饰类 | public class MyClass { public void method1() { synchronized(MyClass.class) { // 同步代码块 } } public synchronized void method2() { // 同步方法 } } |
ReentrantReadWriteLock:
Atomic 全家桶:
Concurrent全家桶:
Redisson
public static void main(String[] args) throws InterruptedException {
// connects to 127.0.0.1:6379 by default
RedissonClient redisson = Redisson.create();
RLock lock = redisson.getLock("lock");
lock.lock(2, TimeUnit.SECONDS);
Thread t = new Thread() {
public void run() {
RLock lock1 = redisson.getLock("lock");
lock1.lock();
lock1.unlock();
};
};
t.start();
t.join();
redisson.shutdown();
}
// 加锁以后10秒钟自动解锁
// 无需调用unlock方法手动解锁
lock.lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
try {
...
} finally {
lock.unlock();
}
}
RLock lock = redisson.getLock("anyLock");
lock.lockAsync();
lock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = lock.tryLockAsync(100, 10, TimeUnit.SECONDS);
2. 公平锁(Fair Lock)
public static void main(String[] args) throws InterruptedException {
// connects to 127.0.0.1:6379 by default
RedissonClient redisson = Redisson.create();
RLock lock = redisson.getFairLock("test");
int size = 10;
List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < size; i++) {
final int j = i;
Thread t = new Thread() {
public void run() {
lock.lock();
lock.unlock();
};
};
threads.add(t);
}
for (Thread thread : threads) {
thread.start();
thread.join(5);
}
for (Thread thread : threads) {
thread.join();
}
}
// 10秒钟以后自动解锁
// 无需调用unlock方法手动解锁
fairLock.lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
...
fairLock.unlock();
RLock fairLock = redisson.getFairLock("anyLock");
fairLock.lockAsync();
fairLock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = fairLock.tryLockAsync(100, 10, TimeUnit.SECONDS);
3. 联锁(MultiLock)
public static void main(String[] args) throws InterruptedException {
// connects to 127.0.0.1:6379 by default
RedissonClient client = Redisson.create();
// 同时加锁:lock1 lock2 lock3 所有的锁都上锁成功才算成功。
RLock lock1 = client.getLock("lock1");
RLock lock2 = client.getLock("lock2");
RLock lock3 = client.getLock("lock3");
Thread t = new Thread() {
public void run() {
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
lock.unlock();
};
};
t.start();
t.join(1000);
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
lock.unlock();
}
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 给lock1,lock2,lock3加锁,如果没有手动解开的话,10秒钟后将会自动解开
lock.lock(10, TimeUnit.SECONDS);
// 为加锁等待100秒时间,并在加锁成功10秒钟后自动解开
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();
4. 红锁(RedLock)
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 红锁在大部分节点上加锁成功就算成功。
lock.lock();
...
lock.unlock();
。
public static void main(String[] args) throws InterruptedException {
// connects to 127.0.0.1:6379 by default
RedissonClient client1 = Redisson.create();
RedissonClient client2 = Redisson.create();
RLock lock1 = client1.getLock("lock1");
RLock lock2 = client1.getLock("lock2");
RLock lock3 = client2.getLock("lock3");
Thread t1 = new Thread() {
public void run() {
lock3.lock();
};
};
t1.start();
t1.join();
Thread t = new Thread() {
public void run() {
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
lock.unlock();
};
};
t.start();
t.join(1000);
lock3.forceUnlock();
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 给lock1,lock2,lock3加锁,如果没有手动解开的话,10秒钟后将会自动解开
lock.lock(10, TimeUnit.SECONDS);
lock.unlock();
client1.shutdown();
client2.shutdown();
}
5. 读写锁(ReadWriteLock)
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常见的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();
public static void main(String[] args) throws InterruptedException {
// connects to 127.0.0.1:6379 by default
RedissonClient redisson = Redisson.create();
final RReadWriteLock lock = redisson.getReadWriteLock("lock");
lock.writeLock().tryLock();
Thread t = new Thread() {
public void run() {
RLock r = lock.readLock();
// 10秒钟以后自动解锁,无需调用unlock方法手动解锁
//lock.readLock().lock(10, TimeUnit.SECONDS);
r.lock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
r.unlock();
};
};
t.start();
t.join();
lock.writeLock().unlock();
t.join();
redisson.shutdown();
}
6. 信号量(Semaphore)
public static void main(String[] args) throws InterruptedException {
// connects to 127.0.0.1:6379 by default
RedissonClient redisson = Redisson.create();
RSemaphore s = redisson.getSemaphore("test");
s.trySetPermits(5);
s.acquire(3);
Thread t = new Thread() {
public void run() {
RSemaphore s = redisson.getSemaphore("test");
s.release();
s.release();
}
};
t.start();
//或
s.acquire(4);
redisson.shutdown();
}
7. 可过期性信号量(PermitExpirableSemaphore)
public static void main(String[] args) throws InterruptedException {
// connects to 127.0.0.1:6379 by default
RedissonClient redisson = Redisson.create();
RPermitExpirableSemaphore s = redisson.getPermitExpirableSemaphore("test");
s.trySetPermits(1);
// 获取一个信号,有效期只有2秒钟。
String permitId = s.tryAcquire(100, 2, TimeUnit.SECONDS);
Thread t = new Thread() {
public void run() {
RPermitExpirableSemaphore s = redisson.getPermitExpirableSemaphore("test");
try {
String permitId = s.acquire();
s.release(permitId);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
};
t.start();
t.join();
s.tryRelease(permitId);
}
8. 闭锁(CountDownLatch)
public static void main(String[] args) throws InterruptedException {
// connects to 127.0.0.1:6379 by default
RedissonClient redisson = Redisson.create();
ExecutorService executor = Executors.newFixedThreadPool(2);
final RCountDownLatch latch = redisson.getCountDownLatch("latch1");
latch.trySetCount(1);
// 在其他线程或其他JVM里
executor.execute(new Runnable() {
public void run() {
latch.countDown();
}
});
executor.execute(new Runnable() {
public void run() {
try {
latch.await(550, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
}
Zookeeper

1. (可重入锁 Shared Reentrant Lock)
public class ExampleClientThatLocks {
private final InterProcessMutex lock;
private final FakeLimitedResource resource;
private final String clientName;
public ExampleClientThatLocks(
CuratorFramework client, String lockPath, FakeLimitedResource resource, String clientName) {
this.resource = resource;
this.clientName = clientName;
lock = new InterProcessMutex(client, lockPath);
}
public void doWork(long time, TimeUnit unit) throws Exception {
if (!lock.acquire(time, unit)) {
throw new IllegalStateException(clientName + " could not acquire the lock");
}
try {
System.out.println(clientName + " has the lock");
resource.use();
} finally {
System.out.println(clientName + " releasing the lock");
//释放锁
lock.release();
}
}
}
2. 不可重入锁(Shared Lock)
3. 可重入读写锁(Shared Reentrant Read Write Lock)
InterProcessReadWriteLock
InterProcessLock
4. 信号量(Shared Semaphore)
public void returnAll(Collection<Lease> leases)
public void returnLease(Lease lease)
public Lease acquire()
public Collection<Lease> acquire(int qty)
public Lease acquire(long time, TimeUnit unit)
public Collection<Lease> acquire(int qty, long time, TimeUnit unit)
InterProcessSemaphoreV2
Lease
SharedCountReader
5. 多锁对象(Multi Shared Lock)
InterProcessMultiLock
InterProcessLock
public InterProcessMultiLock(List<InterProcessLock> locks)
public InterProcessMultiLock(CuratorFramework client, List<String> paths)
6. 完整锁示例
public class LockingExample {
private static final int QTY = 5;
private static final int REPETITIONS = QTY * 10;
private static final String PATH = "/examples/locks";
public static void main(String[] args) throws Exception {
// all of the useful sample code is in ExampleClientThatLocks.java
// FakeLimitedResource simulates some external resource that can only be access by one process at a time
final FakeLimitedResource resource = new FakeLimitedResource();
ExecutorService service = Executors.newFixedThreadPool(QTY);
final TestingServer server = new TestingServer();
try {
for (int i = 0; i < QTY; ++i) {
final int index = i;
Callable<Void> task = new Callable<Void>() {
public Void call() throws Exception {
CuratorFramework client = CuratorFrameworkFactory.newClient(
server.getConnectString(), new ExponentialBackoffRetry(1000, 3));
try {
client.start();
ExampleClientThatLocks example =
new ExampleClientThatLocks(client, PATH, resource, "Client " + index);
for (int j = 0; j < REPETITIONS; ++j) {
example.doWork(10, TimeUnit.SECONDS);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
e.printStackTrace();
// log or do something
} finally {
CloseableUtils.closeQuietly(client);
}
return null;
}
};
service.submit(task);
}
service.shutdown();
service.awaitTermination(10, TimeUnit.MINUTES);
} finally {
CloseableUtils.closeQuietly(server);
}
}
}
以上就是我对锁的总结。分布式锁不是完美的,总会有问题;如:在redis中,lockName和已有的key不能重名 !unlock的前提是lock成功!必须要设计自己的兜底方案......
本文分享自微信公众号 - 京东云开发者(JDT_Developers)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。