1.减少锁的持有时间(具体到方法)
2.减小锁的粒度
将大对象,拆成小对象,大大增加并行度,降低锁竞争. 如此一来偏向锁,轻量级锁成功率提高. 使用ReadWriteLock就可以做到读写分离,比如ConcurrentHashMap中使用的锁分离
3. 锁粗化:多个同步块合并,减少对锁的请求和释放
4. 锁消除:锁消除是Java虚拟机在JIT编译时(jdk1.6以后),通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁,通过锁消除,可以节省毫无意义的请求锁时间。
可以通过启动将其优化,将锁消除,前提是java必须运行在server模式(server模式会比client模式作更多的优化),同时必须开启逃逸分析:
-server -XX:+DoEscapeAnalysis -XX:+EliminateLocks
其中+DoEscapeAnalysis表示开启逃逸分析,+EliminateLocks表示锁消除
5.引用ThreadLocal
除了控制有限资源访问外, 我们还可以增加资源来保证对象线程安全.
对于一些线程不安全的对象, 例如SimpleDateFormat, 与其加锁让100个线程来竞争获取,
不如准备100个SimpleDateFormat, 每个线程各自为营, 很快的完成format工作.
public class ThreadLocalDemo {
public static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal();
public static void main(String[] args){
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
service.submit(new Runnable() {
@Override
public void run() {
if (threadLocal.get() == null) {
threadLocal.set(new SimpleDateFormat("yyyy-MM-dd"));
}
System.out.println(threadLocal.get().format(new Date()));
}
});
}
}
}
对于set方法, 先获取当前线程对象, 然后getMap()获取线程的ThreadLocalMap, 并将值放入map中.
该map是线程Thread的内部变量, 其key为threadlocal, vaule为我们set进去的值
手动释放: 调用threadlocal.set(null)或者threadlocal.remove()即可
自动释放: 关闭线程池, 线程结束后, 自动释放threadlocalmap.