synchronized 锁的是对象不是代码
对某个对象加锁
public class T{
private int count = 10;
private Object o = new Object();
public void m(){
synchronized(o){ //任何线程要执行下面的代码,必须先拿到o的锁
count--;
system.out.println(Thread.cunrentThread().getName() + "count = " + count);
}
}
}
对象头64位 有两位实现锁
public class T{
private int count = 10;
public void m(){
synchronized(this){ //任何线程要执行下面的代码,必须先拿到this的锁
count--;
system.out.println(Thread.cunrentThread().getName() + "count = " + count);
}
}
}
public class T{
private int count = 10;
//任何线程要执行下面的代码,必须先拿到锁
public synchronized void m(){
count--;
system.out.println(Thread.cunrentThread().getName() + "count = " + count);
}
}
static类型
public class T{
private static int count = 10;
public synchronized static void m(){ //这里等同于synchronized (T.class)
count--;
system.out.println(Thread.cunrentThread().getName() + "count = " + count);
}
public static void m(){
synchronized (T.class)
count--;
}
}
synchronized既保证了原子性又保证了可见性
public class T implements Runnable{
private int count = 10;
public /*synchronized*/ void run(){
count --;
System.out.println(count);
}
public static void main(String[] args){
T t = new T();
for(int i = 0; i<100; i++){
new Thread( t, "THREAD" + i ).start();
}
}
}
同步方法和非同步方法是否可以同时调用 可以
public class T{
public synchronized void m1(){
System.out.println("m1 start...");
try{
Thread.sleep(10000);
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("m1 end");
}
public void m2(){
try{
Thread.sleep(5000);
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("m2");
}
public static void main(String[] args){
T t = new T();
/*new Thread(()->t.m1(),"t1").start();
new Thread(()->t.m2(),"t2").start();*/
new Thread(t::m1,"t1").start();
new Thread(t::m2,"t2").start();
}
}
m1 start...
m2
m1 end
模拟银行账户 对业务写方法加锁 对业务读方法不加锁
public class Account {
String name;
double balance;
public synchronized void set(String name, double balance) {
this.name = name;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.balance = balance;
}
public /* synchronized */ double getBalance(String name) {
return this.balance;
}
public static void main(String[] args) {
Account a = new Account();
new Thread(() -> a.set("zhangsan", 100.0)).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(a.getBalance("zhangsan"));
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(a.getBalance("zhangsan"));
}
}
==
synchronized 可重入锁 必须指同一个线程里面
如果程序中出现异常 锁会被释放
==
synchronized 的底层实现:
JDK早期的时候 重量级 - OS
后来的改进
锁升级的概念:
我就是厕所所长(一、二)
sync(Object)
markWord 记录这个线程ID (偏向锁)
如果有线程争用:升级为 自旋锁 用户态 执行时间短(加锁代码)线程数少
10次之后
升级为 重量级锁 - OS 申请资源加锁 内核态 执行时间长、线程数多 等待队列
==
synchronized(Object)
“Object”不能用String常量 Integer Long
==
final Object o = new Object();
synchronized(o)
==