1. 在多线程并发的场景下,使用锁来控制多个任务对同一共享资源的访问,拿到锁的任务优先访问公共资源
//并发的用户数
private static final int threadNum = 10;
//倒计数器(发令抢),用于制造线程的并发执行
private static CountDownLatch cdl = new CountDownLatch(threadNum);
public void run(){
try{
cdl.await();//线程运行到这里等待,等待发令枪计数器变为0
}catch(InterruptedException e){
e.printStackTrace();
}
//线程结束后,所有线程同时执行换行给printer 发送打印指令
Printer.print(Thread.currentThread().getName()+"");
}
public static void main(String[] args){
for(int i=0;i<threadNum;i++){
new Thread(new PrintTask("sssssss")).start();
cdl.countDown();
}
}
///以上存在线程安全问题:
1. 使用 synchronized
public void run(){ try{ cdl.await();//线程运行到这里等待,等待发令枪计数器变为0 }catch(InterruptedException e){ e.printStackTrace(); } //同步 synchronized(cdl){ Printer.print(Thread.currentThread().getName()+""); } }
2. 线程加锁
private Lock lock=new ReentrantLock(); public void run(){ try{ cdl.await();//线程运行到这里等待,等待发令枪计数器变为0 }catch(InterruptedException e){ e.printStackTrace(); } // lock.lock(); try{ Printer.print(Thread.currentThread().getName()+""); }catch(Exception e){ }finally{ lock.unlock(); }}
redis分布式锁
public class RedisLock implements Lock{
private static final String LOCK_KEY="lock";
private ThreadLocal<String> local=new ThreadLocal<String>();//线程传值
//阻塞时锁
public void lock(){
if(tryLock()){
return;
}else{
Thread.sleep(200); //使用trycatch包围
lock();
}
}
//非阻塞锁
public boolean tryLock(){
String uuid=UUID.randomUUID().toString();
Jedis redis=new Jedis("localhost");
String ret = redis.set(LOCK_KEY,uuid,"NX","PX",100);
if(ret!=null&&ret.equals("OK")){
local.set(uuid);
return true;
}
return false;
}
//解锁
public void unlock(){
String script=FileUtils.readFileByLines("lua脚本文件地址"); //读取lua脚本文件
Jedis redis=new Jedis("localhost");
List<String> keys=new ArrayList<String>();
keys.add(LOCK_KEY);
List<String> args=new ArrayList<String>();
keys.add(local.get());//get uuid
redis.eval(script,keys,args);
}
}
lua脚本
if redis.call("get",KEYS[1])==ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
========================redis加锁==============================================