首页 > 代码库 > 4.多线程之同步

4.多线程之同步

一、同步:synchronized

   同步 并发 多个线程访问同一资源,确保资源安全---->线程安全

  • 同步块:

       Synchronized(引用类型 | this | 类.class){

       }

  • 同步方法: public static synchronized void....   ---->Web12306

   web12306代码实现:

package com.cust.syn;/** *  * 描述:同步 并发 多个线程访问同一资源  * synchronized 线程安全 * @author cookie */public class SynDemo01 {	public static void main(String[] args) {		//真实角色 		Web12306 w = new Web12306();		//三个代理角色		Thread t1 = new Thread(w,"路人甲");		Thread t2 = new Thread(w,"黄牛乙");		Thread t3 = new Thread(w,"攻城狮");		t1.start();		t2.start();		t3.start();	}}class Web12306 implements Runnable {	private boolean flag = true;    int num = 10;	@Override	public void run() {		while(flag){			test5();		}	}		//锁定资源不正确 --->线程不安全 速率比较高	public void test5() {		// a b c		synchronized ((Integer) num) { // 锁定			if (num <= 0) {				flag = false;// 线程结束				return;			}			// a b c			try {				Thread.sleep(500);// Runnable无法往外抛出异常			} catch (InterruptedException e) {				e.printStackTrace();			}			System.out.println(Thread.currentThread().getName() + "抢到了第张"+ num-- + "票");		}	}// a b = 0 c = -1		//锁定范围不正确 --->线程不安全 速率比较高	public void test4(){		// a b c		synchronized(this){  // 锁定 调用此方法的对象 即 Web12306			if(num <=0){				flag = false;//线程结束				return;			}		}		// a b c		try {			Thread.sleep(500);//Runnable无法往外抛出异常		} catch (InterruptedException e) {			e.printStackTrace();		}		System.out.println(Thread.currentThread().getName()+"抢到了第张"+ num-- +"票");	}//a   b = 0  c = -1		//锁定同步块 --->线程安全 速率较低	public void test3(){		synchronized(this){  // 锁定 调用此方法的对象 即 Web12306			if(num <=0){				flag = false;//线程结束				return;			}			try {				Thread.sleep(500);//Runnable无法往外抛出异常			} catch (InterruptedException e) {				e.printStackTrace();			}			System.out.println(Thread.currentThread().getName()+"抢到了第张"+ num-- +"票");		}	}	//锁定方法 --->线程安全 速率较低	public synchronized void test2(){		if(num <=0){			flag = false;//线程结束			return;		}		try {			Thread.sleep(500);//Runnable无法往外抛出异常		} catch (InterruptedException e) {			e.printStackTrace();		}		System.out.println(Thread.currentThread().getName()+"抢到了第张"+ num-- +"票");		}	//并发 不处理 ---->线程不安全   速率较低	public void test1(){		if(num <=0){			flag = false;//线程结束			return;		}		try {			Thread.sleep(500);//Runnable无法往外抛出异常		} catch (InterruptedException e) {			e.printStackTrace();		}		System.out.println(Thread.currentThread().getName()+"抢到了第张"+ num-- +"票");		}}

 二、单例模式 

  懒汉式 和 饿汉式

package com.cust.syn;/** * 单例模式 *   gc  JVM   垃圾桶  Runtime * 懒汉式:  double checking 双重检查 *   1.构造器私有化 *   2.声明一个私有的静态变量 *   3.创建一个共有的静态方法,访问变量,并确保有变量 *  饿汉式: *    * @author cookie */public class SingletonDemo {}/** *   懒汉式:  double checking 双重检查 *   1.构造器私有化 *   2.声明一个私有的静态变量 *   3.创建一个共有的静态方法,访问变量,并确保有变量 * @author cookie */class JVM{	private static JVM jvm;	private JVM(){	}	public static JVM getInstance(){		if(null == jvm){ //提高效率,在对象已经存在的情况下不进入该方法			synchronized(JVM.class){  //静态方法中不能调用this				if(null==jvm){  //如果不存在,则创建对象 安全					jvm = new JVM();				}			}		}		return jvm;	}}/** * 饿汉式: *   1.构造器私有化 *   2.声明一个私有的静态变量,并同时实例化该变量 *   3.创建一个共有的静态方法,访问变量 * @author cookie */class JVM2{	private static JVM2 jvm = new JVM2();	private JVM2(){	}	public static JVM2 getInstance(){ //不使用这个方法,变量可能被初始化		return jvm;	}}/** * 类在使用时加载,延缓加载时间(MyJvm)  饿汉式推荐 * @author cookie */class JVM3{	private static class MyJvm{		private static JVM3 jvm = new JVM3();	}	private JVM3(){	}	public static JVM3 getInstance(){//不使用这个方法,不会加载MyJvm		return MyJvm.jvm;	}}

  三、死锁:过多的同步容易造成死锁

/** *  * 描述:死锁:过多的同步容易造成死锁 * @author cookie */public class SynDemo03 {	public static void main(String[] args) {		Object g = new Object();		Object m = new Object();		Test t1 = new Test(g,m);		Test2 t2 = new Test2(g,m);		Thread proxy = new Thread(t1);		Thread proxy2 = new Thread(t2);		proxy.start();		proxy2.start();	}}class Test implements Runnable{	Object goods;	Object money;	public Test(Object goods, Object money) {		this.goods = goods;		this.money = money;	}	@Override	public void run() {		test();	}	public void test(){		synchronized(goods){			try {				Thread.sleep(200);			} catch (InterruptedException e) {				e.printStackTrace();			}			synchronized(money){							}		}		System.out.println("一手给钱");	}}class Test2 implements Runnable{	Object goods;	Object money;	public Test2(Object goods, Object money) {		this.goods = goods;		this.money = money;	}	@Override	public void run() {		test();	}	public void test(){		synchronized(money){			try {				Thread.sleep(200);			} catch (InterruptedException e) {				e.printStackTrace();			}			synchronized(goods){							}		}		System.out.println("一手给货");	}}

  四、解决死锁:生产者消费者 信号量法

package com.cust.pro;/** * 一个场景 共同的资源 生产者消费者模式 信号灯法 Object: wait() 释放锁 等待 sleep()不释放锁 * notify()/notifyAll() 唤醒等待 *  * @author cookie */class Movie {	private String pic;	// 信号灯	// 信号灯法	// flag---->T 生产者生产,消费者等待,生产完生产毕后,唤醒消费者	// flag---->F 消费者消费,生产者等待,消费者消费完毕后,唤醒生产者	private boolean flag = true;	public synchronized void play(String pic) {		if (!flag) {// 消费者消费 生产者等待			try {				this.wait();			} catch (InterruptedException e) {				e.printStackTrace();			}		}		try {			Thread.sleep(100);		} catch (InterruptedException e1) {			e1.printStackTrace();		}		// 生产结束		this.pic = pic;		System.out.println("生产了:" + pic);		// 唤醒消费者,		this.notifyAll();		// 生产者结束		this.flag = false;	}	public synchronized void watch() {		if (flag) {// 生产者生产,消费者等待			try {				this.wait();			} catch (InterruptedException e) {				e.printStackTrace();			}		}		// 消费者消费		try {			Thread.sleep(200);		} catch (InterruptedException e) {			e.printStackTrace();		}		// 消费完毕		System.out.println("消费了:" + this.pic);		// 唤醒生产者		this.notify();		// 消费者等待		this.flag = true;	}} class Player implements Runnable{	private Movie m;	public Player(Movie m) {		this.m = m;	}	@Override	public void run() {		for (int i = 0; i < 20; i++) {			if(0==i%2){				m.play("左青龙");			}else{				m.play("右白虎");			}		}	}} class Watcher implements Runnable{	private Movie m;	public Watcher(Movie m) {		this.m = m;	}	@Override	public void run() {		for (int i = 0; i < 20; i++) {			m.watch();		}	}	}public class App {	public static void main(String[] args) {		//共同的资源		Movie m = new Movie();		//多线程		Player p = new Player(m);		Watcher w = new Watcher(m);				new Thread(p).start();		new Thread(w).start();	}}

  

4.多线程之同步