并发编程第一天

synchronized认识

synchronized修饰的地方

1. 修饰对象,就是,新建一个对象,修饰她,这样每一次执行syschronized包裹的代码块,必须取得拿
到对象锁然后才可以运行这个代码块
2. 修饰公共的方法,这个锁的拥有者就是thsi,就是这个类的实例
3. 修饰静态的方法,这个所得拥有者就是test.class

脏读

1. 同步方法,与不同步方法会同时进行,不会相互影响.
![](https://i.imgur.com/rvb2xax.jpg)
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();
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值