ThreadSafe
多线程并发
public class Tickets implements Runnable{
private int ticket = 100;
public void run(){
while(true){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() + "出售票" + ticket--);
}
}
}
}
pubilc static void main(String[] args){
Tickets ts = new Ticket();
Thread t0 = new Thread(ts);
Thread t1 = new Thread(ts);
Thread t2 = new Thread(ts);
t0.start();
t1.start();
t2.start();
}
同步代码块解决线程问题:synchronized(Object obj){线程要操作的代码块}
private Object obj = new Object();
public void run(){
while(true){
synchronized(obj){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() + "出售票" + ticket--);
}
}
}
}
同步对象:
任意对象,对象监听器
没有锁的线程不能执行只能等待,遇见同步代码块,
- 判断对象锁还有没有
- 有,拿走,等执行完成才放回去
- 没有就只有等
- 将线程共享部分抽取出来
private int ticket = 100;
public void run(){
while(true){
pay();
}
}
}
public static synchronized void pay(){
if(ticket > 0){]
System.out.println(Thread.currentThread().getName() + "出售票" + ticket--);
}
//在同步方法中,对象锁是this。但是在静态方法中,对象锁不是this,this属于对象,优先于static,是本类自己.class
Lock
在线程中,只有出了同步代码块才会释放对象锁,但是要是出现了异常就不会释放了。所以在jdk5以后就使用Lock接口
public void lock()
public void unlock()
死锁问题
锁的嵌套
出现了互锁
- 确保锁唯一
- 构造方法私有,只能通过静态方法来调用,且不可修改
public class lockA{
public static final LockA lockA = new LockA();
private LockA(){
}
}
public class lockB{
public static final LockB lockB = new LockB();
private LockB(){
}
}
public class DeadLock implements Runnable{
private int i = 0;
public void run(){
while(ture){
if(i%2 == 0){
//先进入A同步,在进入B同步
synchronized(LockA.locka){
System.out.println("if...locka");
synchronized(LockB.lockb){
System.out.println("else...lockb");
}
}
}else{
synchronized(LockB.lockb){
System.out.println("if...lockb");
synchronized(LockA.locka){
System.out.println("else...locka");
}
}
}
}
}
}
线程间通信
多个线程操作同一个数据,但是操作的动作可能并不相同,通过一定的手段将各个线程有效的利用,既--等待唤醒机制
-
public void wait()释放正在执行的线程的执行权,放到存储池
-
public void notify()唤醒在线程池中wait()的线程,一次唤醒一个,而且是任意的。
-
public void notifyAll(),唤醒在线程池中所有的wait()线程唤醒
-
[x] 线程之间是不是所有的数据都锁上了
-
[x] 是不是用的同一个锁
扫描二维码关注公众号,回复: 182350 查看本文章
public class Resource{
public String name;
public String sex;
public boolean flag;//唤醒标识
public Resource(String name,String sex){
this.name = name;
}
}
public class InputThread implements Runnable{
private Resource r = null;
public InputThread(Resource r){
this.r = r;
}
public void run(){
int i = 0;
while(true){
synchronized(r){
if(r.flag){
try{
//必须是锁对象调用
r.wait();
}catch(Exception ex){
System.out.println(ex.getMessage());
}
}
if(i%2 == 0){
r.name = "张三";
r.sex = "男";
}else{
r.name = "lisi";
r.sex = "nv";
}
i++;
//执行完成,将标识修改,并唤醒对方。
r.flag = true;
r.notify();
}
}
}
}
public class OutputThread{
private Resource r = null;
public void run(){
//使用同一个对象锁
synchronized(r){
while(true){
if(r.flag){
try{
//必须是锁对象调用
r.wait();
}catch(Exception ex){
System.out.println(ex.getMessage());
}
System.out.println(r.name);
//执行完成,将标识修改,并唤醒对方。
r.flag = false;
r.notify();
}
}
}
public OutputThread(Resource r){
this.r = r;
}
}
public class ThreadDemo{
public static void main(String[] args){
Resource r = new Resource();
InputThread int = new InputThread(r);
OutputThread outt = new OutputThread(r);
Thread in = new Thread(in);
Thread out = new Thread(out);
}
}
为什么是Object的方法
对于线程来说,要同步必须操作同一个锁对象
才可以,如果是使用各自来做自己的线程唤醒对象就不能实现同一个锁对象
,并且对于实现类来说,调用者是谁?
==所有的线程的等待唤醒必须是锁对象调用,调用者是谁?任何方法都需要被调用,本类线程类是没有wait方法的,只有调用父类的super(),但是父类也没有这个方法,调用这个的锁对象是谁就由谁来调用,所以,同步的等待唤醒方法都是Object类的方法==