一、前言
二、锁的建议
1、锁的分化,具体可以借鉴block queue的take与put分锁
2、锁定定义块合适,不适合太大也不适合太小
3、JAVA虚拟机自带锁一步步:
3.1 锁偏向(统一进程直接进入同步)------》
3.2 轻量级锁(开启:-XX:+UseBiasedLockong)------》
3.3 自旋锁(空循环,等待)-----》
3.4锁消除(是否真需要同步分析,开启逃逸分析:-XX:+EliminateLocks)
4、ThreadLocal工具,原理:开很多线程来做同一份工作。缺点:线程不安全,不能操作共享数据
应用场景:
* 应用场景: *1、存放当前session用户:quake want的jert 2、存放一些context变量,比如webwork的ActionContext 3、存放session,比如Spring hibernate orm的session
package lock;
import jDKMulit.CountDownLathDemo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by ycy on 16/1/14.
*/
public class ThreadLocalDemo_Gc {
static volatile ThreadLocal<SimpleDateFormat> t1=new ThreadLocal<SimpleDateFormat>(){
@Override
protected void finalize() throws Throwable{
System.out.println(this.toString()+" is gc");
}
};
static volatile CountDownLatch cd=new CountDownLatch(1000);//线程计算器 ,叨叨1000次调用之后不在等待
public static class ParseDare implements Runnable{
int i=0;
public ParseDare(int i){
this.i=i;
}
public void run() {
try {
if (t1.get()==null){
t1.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"){
@Override
protected void finalize() throws Throwable {
System.out.println(this.toString()+" is gc");
}
});
System.out.println(Thread.currentThread().getId()+"create SimpleDatefromat");
}
Date t=t1.get().parse("2015-03-29 19:29:"+i%60);
} catch (ParseException e) {
e.printStackTrace();
}finally {
cd.countDown();
}
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService es= Executors.newFixedThreadPool(10);
for (int i = 0; i <1000 ; i++) {
es.execute(new ParseDare(i));
}
cd.await();
System.out.println("misson complete");
t1=null;
System.gc();
System.out.println("frist FC complete");
//在设置ThreadLocal的时候,会清楚ThreadMap中无效的对象
t1=new ThreadLocal<SimpleDateFormat>();
cd=new CountDownLatch(1000);
for (int i = 0; i <1000 ; i++) {
es.execute(new ParseDare(i));
}
cd.await();
Thread.sleep(1000);
System.gc();
System.out.println(" second GC complete");
}
}
5、牛叉:忘掉我们该死得锁是哟高CAS操作,这么做直接跟CPU交道适用Atomic Integer long reference 等等,都可以适用。
package lock;
import java.util.concurrent.atomic.AtomicStampedReference;
/**
* Created by ycy on 16/1/14.
* cas:比较交换
* 用AtomicStampedReference 封装对象;
* 景:对数据库进行查询更换,例如消费充值等等
*/
public class AtomicStampedRefrenceDemo {
static AtomicStampedReference<Integer> money=new AtomicStampedReference<Integer>(19,0);//引用对象,初始时间戳
public static void main(String[] args) {
//模拟多个线程更新数据库,为用户充值
for (int i = 0; i <3 ; i++) {
final int timestamp= money.getStamp();//获取时间戳
new Thread(){
@Override
public void run() {
while (true){
while (true){
Integer m=money.getReference();
if(m<20){
if (money.compareAndSet(m,m+20,timestamp,timestamp+2)){
System.out.println("余额小于20元,充值成功,余额为"+money.getReference()+"元");
break;
}
}else{
System.out.println("余额大于20,无须充值");
break;
}
}
}
}
}.start();
}
//用户消费线程 模拟
new Thread(){
@Override
public void run() {
for (int i = 0; i <3 ; i++) {
while(true){
int timestamp=money.getStamp();
Integer m=money.getReference();
if (m>10){
System.out.println("大于10元");
if (money.compareAndSet(m,m-10,timestamp,timestamp+1)){
System.out.println("成功消费10元,余额为"+money.getReference());
break;
}
}else{
System.out.println("没有足够资金");
break;
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
6、死锁产生的要素“
6.1、互斥使用(资源独占)
一个资源每次只能给一个进程使用
6.2、不可强占(不可剥夺)
资源申请者不能强行的从资源占有者手中夺取资源,资源只能由占有者自愿释放
6.3、请求和保持(部分分配,占有申请)
一个进程在申请新的资源的同时保持对原有资源的占有(只有这样才是动态申请,动态分配)
6.4、循环等待
存在一个进程等待队列
{P1 , P2 , … , Pn},
其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,形成一个进程等待环路