1、atomic和sync以及LongAddr区别
为什么atomic比sync快?
因为syncronized比atomic慢。以为syncronized加锁。atomic不加锁
为什么LongAddr比atomic快?
像a++这块
atomic是cas无锁自旋。。而LongAddr是分段锁概念。把一个值放到一个数组里。数组长度为4时候。0到1000线程。其中250个线程锁在第一个数组元素里。250锁在第二个数组元素。。每一个往上递增的结果加到一起。
2、可重入锁ReentrantLock
synchronized本身也是可重入锁的一种,什么是可重入,意思就是我锁了一下还可以对同样的这把锁再锁一下。synchronized必须是可重入的因为。子类继承父类的同步方法。是可以实现的。如果不是重入锁。这里是无法实现的。
package com.example.demo.gc20;
import java.util.concurrent.TimeUnit;
public class T01_ReentrantLock1 {
synchronized void m1(){
for (int i=0;i<10;i++){
try{
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(i);
if (i == 2) m2();
}
}
synchronized void m2(){
System.out.println("m2 ...");
}
public static void main(String[] args) {
T01_ReentrantLock1 t = new T01_ReentrantLock1();
new Thread(t::m1).start();
try {
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
####这个程序m1方法里面做了循环每次睡1秒。每隔一秒打印一个。接下来调m2,如果synchronized不能重入。则会出现一种情况。必须等第一个线程结束了。因为两线程之间肯定会争用。当m1方法里面调用m2可以。。。也就是synchronized可以调用synchronized。这样的锁就是可重入锁
子类和父类如果是synchronized(this)就是同一把锁。
ReentrantLock是可以替代synchronized的
package com.example.demo.gc20;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class T02_ReentrantLock2 {
Lock lock = new ReentrantLock();
void m1(){
try{
// 上锁
lock.lock();
for(int i=0;i<10;i++){
TimeUnit.SECONDS.sleep(1);
System.out.println(i);
if (i == 2) m2();
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
void m2(){
try {
lock.lock();
System.out.println("m2 ....");
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
T02_ReentrantLock2 t = new T02_ReentrantLock2();
new Thread(t::m1).start();
try {
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
// new Thread(t::m2).start();
}
}
用synchronized和lock结果一样
既然reentrantlock和synchronized差不多。那么要reentrantLock有什么用?
因为他比sync强大。他可以尝试tryLock锁定。不必担心锁定与否,方法都会继续执行。但是synchronized如果失败必定阻塞。
synchronized是可以自动解锁的。但reentrantLock必须在finally块调用lock.unlock()方法解锁
####比如5秒钟你把程序执行完就可能得到这把锁。如果得不到就不行。这样的程序必须用reetrantLock
package com.example.demo.gc20;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class T03_ReentrantLock3 {
Lock lock = new ReentrantLock();
void m1(){
try{
lock.lock();
for(int i=0;i<3;i++){
TimeUnit.SECONDS.sleep(1);
System.out.println(i);
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
void m2(){
// 尝试上锁
boolean locked = false;
try {
locked = lock.tryLock(5, TimeUnit.SECONDS);
System.out.println("m2...." +locked);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
if (locked) lock.unlock();
}
}
public static void main(String[] args) {
T03_ReentrantLock3 t = new T03_ReentrantLock3();
new Thread(t::m1).start();
try{
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
new Thread(t::m2).start();
}
}