Java多线程基础之线程同步与锁定

线程同步与锁定

由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突严重的这个问题,Java语言提供了专门的机制以解决这类冲突,有效避免了同一个数据对象被多个线程同时访问,由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们针对方法提出一整套机制,这套机制就是sychronized关键字;

sychronized:

HashTable 和StringBuffer底部均有使用 同步代码或同步块;

 * 一:同步块(sychronized(this|.class|引用类型)

package Tread;

public class Demo  {
	public static void main(String[] args) {
		Web12306 wb = new Web12306();
		Thread t1 = new Thread(wb, "黄牛");
		Thread t2 = new Thread(wb, "黄牛2");
		Thread t3 = new Thread(wb, "工程师");
		t1.start();
		t2.start();
		t3.start();
	}
}
class Web12306 implements Runnable {
	int num = 10;
	private boolean flag = true;

	@Override
	public void run() {
		while (true) {
			test1();
		}

	}
     // 线程不安全
	public void test1() {
		if(num<=0) {
			flag=false;
			return;
		}
		try {
			Thread.sleep(500);
		} 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);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了"+num--+"票");
	}

   //锁定this对象
           public void test2() {
		synchronized (this) {
		if (num <= 0) {
			flag = false;
			return;
		}
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "抢到了" + num-- + "票");
	}
	}


}

  / 锁定范围不正确与锁定资源不正确,均会造成线程不安全,错误代码实例

	public void test2() {
		if (num <= 0) {
			flag = false;
			return;
		}
		synchronized (this) {
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "抢到了" + num-- + "票");
	}
	}
	  public void test2() {
		synchronized ((Integer)num) {
		if (num <= 0) {
			flag = false;
			return;
		}
		
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "抢到了" + num-- + "票");
	}
	}

  锁定.class对象

单例设计模式

单例设计模式: 确保一个类只有一个对象
 *   懒汉式
 *  1.构造器私有化,避免外部直接创建对象
 *  2.声明一个私有的静态变量
 *  3.创建一个对外公共的静态方法访问该变量,如果该变量没有对象,创建该对象
 

package Tread;

//单例设计模式:确保一个类只有一个对象
public class SynDemo {
	public static void main(String[] args) {
		Jvmthread jvm1 = new Jvmthread(100);
		Jvmthread jvm2 = new Jvmthread(500);
		new Thread(jvm1).start();
		new Thread(jvm2).start();
	}
}

class Jvmthread implements Runnable {
	private long time;

	public Jvmthread(long time) {
		super();
		this.time = time;
	}

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + "------>" + Jvm.getInstance(time));

	}

}
/**
 * 单例设计模式: 确保一个类只有一个对象
 *  懒汉式 
 *  1.构造器私有化,避免外部直接创建对象 
 *  2.声明一个私有的静态变量
 * 3.创建一个对外公共的静态方法访问该变量,如果该变量没有对象,创建该对象
 */
class Jvm {
	private static Jvm instance = null;

	private Jvm() {

	}

	// 两种方法,一种锁住方法,一种锁住.class文件,注意:静态方法不能存在this对象,所以不能锁住this
	public static Jvm getInstance(long time) {
		if (null == instance) {
			try {
				Thread.sleep(time);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			instance = new Jvm();
		}
		return instance;
	}

	// 提高效率:双重检查 已经有对象,其他线程不用再等待锁
	public static Jvm getInstance2(long time) {
		if (null == instance) {
		synchronized (Jvm.class) {
			if (null == instance) {
				try {
					Thread.sleep(time);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				instance = new Jvm();
			}
		}
		}
		return instance;
	}

}

  饿汉式
 * 1.构造器私有化,避免外部直接创建对象
 * 2.声明一个私有的静态变量,同时创建该对象
 * 3.创建一个对外公共的静态方法访问该变量,如果该变量没有对象,创建该对象

package Tread;

/*****
 * 饿汉式 
 * 1.构造器私有化,避免外部直接创建对象 
 * 2.声明一个私有的静态变量,同时创建该对象
 * 3.创建一个对外公共的静态方法访问该变量,如果该变量没有对象,创建该对象
 */
public class MyJvM {
	private static MyJvM instance=new MyJvM();
	private MyJvM () {

	}
	public static MyJvM  getInstance(long time) {
		return instance;
	}
}

/**优化写法
 * 类在使用的时候才加载,延缓加载时间
 *
 */
class MyJvM3 {
	private static class Jvmholder {
		private static MyJvM3 instance = new MyJvM3();
	}

	private MyJvM3() {

	}

	public static MyJvM3 getInstance() {
		return Jvmholder.instance;
	}

}

  

原文地址:https://www.cnblogs.com/yjxs/p/9848555.html