java基础专栏—ThreadSafe

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){线程要操做的代码块}java

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接口this

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");
                    }
                }
            }
        }
    }
}

线程间通讯

​ 多个线程操做同一个数据,可是操做的动做可能并不相同,经过必定的手段将各个线程有效的利用,既--等待唤醒机制code

  • public void wait()释放正在执行的线程的执行权,放到存储池对象

  • public void notify()唤醒在线程池中wait()的线程,一次唤醒一个,并且是任意的。接口

  • public void notifyAll(),唤醒在线程池中全部的wait()线程唤醒get

  • [x] 线程之间是否是全部的数据都锁上了同步

  • [x] 是否是用的同一个锁

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类的方法==

相关文章
相关标签/搜索