synchronized认识
synchronized修饰的地方
1. 修饰对象,就是,新建一个对象,修饰她,这样每一次执行syschronized包裹的代码块,必须取得拿
到对象锁然后才可以运行这个代码块
2. 修饰公共的方法,这个锁的拥有者就是thsi,就是这个类的实例
3. 修饰静态的方法,这个所得拥有者就是test.class
脏读
1. 同步方法,与不同步方法会同时进行,不会相互影响.

2. 读写不同步会产生脏读现象,怎样避免,需要开启两个线程,一个是读一个是写,还要给两个方法添加
synchronized
public class test1 {
String name ;
double balance;
public synchronized void set(String name,double balance) {
this.name = name;
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
this.balance = balance;
}
public synchronized double getBalance(String name) {
return this.balance;
}
public static void main(String[] args) throws InterruptedException {
test1 aTest1 = new test1();
new Thread(()->aTest1.set("zhangdan",100.0)).start();
new Thread(new Runnable() {
public void run() {
System.out.println("!!!!!!!");
System.out.println(aTest1.getBalance("zhangsan"));
}
}).start();
}
}
这就是一个典型的脏读现象,如果我们没有在getBalance()添加synchronized修饰,那么显示的结果为
!!!!!00000,如果我们添加锁,在调用getbalance(),则没有任何障碍,直接调出.显示结果为,!!!!(过十秒)
100
死锁
两个线程使用同一个对象锁,就会产生死锁,比如,线程曼昆执行时,调用A方法,等待十秒钟,执行B方法
线程长春,先执行B方法,等待十秒钟,执行A方法,这样就会陷入死锁状态
具有重入性
1. A,B方法均有锁,线程曼昆,执行A方法时,曼昆获得对象锁,在曼昆线程里面需要执行B方法,能执行吗
?
答案是可以的,synchronized具有重入性,只要是同一个线程在他执行的阶段他可以多次获得他曾经获得
过的对象锁
2. 子类中的synchronized方法,调用父类中的synchronized方法,
也是可以的,不会造成死锁的
锁会被释放
1. 程序在执行过程中,如果出现异常,默认情况下锁会被释放,所以在
并发处理的过程中,有异常要多加小心,可能这个线程处理一半的数据遇到了异常,锁释放了,那么其他的线程可能就会开启,这时候其他线程拥有的数据就是一半的数据,十分的不安全.怎样避免这种情况??
抛出异常就可以了,继续执行代码!!
volatile
当volatile修饰的变量,当变量修改了之后,会通知所有使用的该变量的线程,这个变量已经过期了,需要来主线程来读一下.
需要了解一下jmm,每一个线程都有一个类似缓存区的东西存在,当从主线程中取得A值之后,就放在了自己的缓冲区中,如果这个线程很忙,那么当其他的线程,改变A的值后,先前的线程会忽略A的值,所以就有valatile存在,只保证线程的可见性.synchronized既能保证可见性也能保证原子性!!
他与synchronized的区别是什么??volatile他能保证可见性,也就是当你修改的的时候,他能保证拿到最新的值,但是写入的不会检查这个值是否最新的值
join
join()方法的作用是调用线程等待该线程结束后,才能继续往下进行
AtomXXX类
Atomxxx类本身方法都是原子性的,但不能保证多个方法连续调用是原子性的
count++
等价于
incrementAndGet();
写一个程序证明AtomXXX()类的多个方法并不构成原子性
AtomXXX()的可以保证可见性么?请写一个程序证明!!
粗粒度的锁比细粒度的锁要慢的多
减少了锁争抢的可能性
锁的对象
锁的对象并不是栈里面的变量,而是堆内存中的地址
public class test2 {
Object o = new Object();
void m() {
synchronized (o) {
while (true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}
public static void main(String[] args) {
test2 t = new test2();
new Thread(t::m,"t1").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
t.o = new Object();
new Thread(t::m,"t2").start();
}
}