一、什么是线程安全
当多个线程访问某个类时,不管运行时环境采用何种类,调度方式或者这些线程将如何交替执行,并且在主要代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么这个类就是线程安全的。
锁的使用能使并行执行的代码变成串行执行,从而实现线程安全。
二、如何优化锁?
1、缩小锁的范围。
2、减小锁的粒度。
3、使用锁分段技术。
三、锁的种类
1、公平锁:synchronized,ReentrantLock。
2、非公平锁:ReentrantLock,CAS(主要用于竞争量不大的情况,不要用在竞争激烈的情况)。
3、独享锁:synchronized,ReentrantLock。
4、共享锁:semaphore。
四、一个分布式锁需要满足的特性
1、互斥性
在任意时刻只有一个客户端可以获取锁。
2、防死锁
即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续客户端能加锁,加一个有效时间。
3、持锁人解锁
加锁和解锁必须是同一个客户端,客户端不能把别人加的锁给解了。
4、可重入
当一个客户端获取锁对象之后,这个客户端可以再次获取该对象上的锁。
五、加锁解锁的流程
加解锁流程六、分布式锁的算法实现
分布式锁的算法实现七、上代码
public class RedisDistributedLock implements Lock{
private ThreadLocal<String> lockContext = new ThreadLocal<String> ();
private long time = 100 ;
private Thread exclusiveOwnerThread ;
public RedisDistributedLock (){
}
//阻塞式获取锁
public void lock() {
while(!tryLock()){
try{
Thread.sleep(time);
}catch(InterruptedException e){
e.printStrackStace();
}
}
}
public boolean tryLock(){
return tryLock(time , TimeUnit.MILLSECOND);
}
private boolean tryLock(long time , TimeUnit timeUnit){
String id = UUID.randomUUID().toString();
Thread t = thread.currentThread();
Jedis jedis = RedisClient.getClient();
if(jedis.setnx("redis",id)==1){
jedis.pexpire( "redis" , timeUnit.toMills(time) );
lockContext.set(id);
setExclusiveOwnerThread(t);
return true;
}else if( exclusiveOwnerThread==t ){
return true;
}
return false;
}
public void unLock(){
String script = null;
try{
Jedis jedis = RedisClient.getClient();
script = inputStream2String(getClass().getSourceAsStream("/redis. script "));
if(lockContext.get()==null){
return ;
}
jedis.eval( script, Arrays.asList("redis"), Arrays.asList(lockContext.get()) );
lockContext.remove();
}catch(Exception e){
e.printStrackTrace();
}
}
public void lockInterruptibly() throws InterruptedException{
if(Thread.interrupted())
throws new InterruptedException ();
while(! tryLock()){
Thread.sleep(time);
}
}
private String inputStream2String (InputStream in) throws IOException{
StringBuffer out = new StringBuffer();
byte[] b = new byte[1024];
for(int n;(n=in.read(b))!=-1;){
out.append(new String(0,n));
}
return out.toString();
}
}
网友评论