本文共 5249 字,大约阅读时间需要 17 分钟。
一、前言
二、锁的建议
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的jert2、存放一些context变量,比如webwork的ActionContext3、存放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 ThreadLocalt1=new ThreadLocal (){ @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 (); 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 AtomicStampedReferencemoney=new AtomicStampedReference (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.1、互斥使用(资源独占)
一个资源每次只能给一个进程使用
6.2、不可强占(不可剥夺)
资源申请者不能强行的从资源占有者手中夺取资源,资源只能由占有者自愿释放
6.3、请求和保持(部分分配,占有申请)
一个进程在申请新的资源的同时保持对原有资源的占有(只有这样才是动态申请,动态分配)
6.4、循环等待
存在一个进程等待队列
{P1 , P2 , … , Pn},
其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,形成一个进程等待环路
转载地址:http://ikrvx.baihongyu.com/