java的Synchronized的用法对象锁、类锁

java的Synchronized的用法

/*
 * synchronized 关键字主要有以下几种用法: 
 * 非静态方法的同步; 	 Synchronized修饰的方法是	对象锁
 * 静态方法的同步; 	 Synchronized修饰的方法是  类锁
 * 代码块。			  静态方法、synchronized(类名.class){}是  类锁
 * 
 * 多线程容易出现问题的原因
 * 		当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,
 * 		另一个线程参与进来执行。导致共享数据的错误。即多个线程执行的不确定性引起执行结果的不稳定。
 * 例子:
 * 		多个线程对账本的共享,会造成操作的不完整性,会破坏数据。
 *		火车站售票,多个窗口同时售票
 *
 * Synchronized(obj){} 同步代码块
 * obj 称为同步监视器,也就是锁,原理是:当线程开始执行同步代码块前,必须先获得对同步代码块的锁定。
 * 并且任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对该同步监视器的锁定
 * 
 * 其中的锁,在非静态方法中可为this,在静态方法中为当前类本身(例如单例模式的懒汉式:Singleton.class)。
 * 
 * synchronized可以修饰方法,修饰代码块,但是不能修饰构造器、成员变量等。
 */
public class Threads3 {
	public static void main(String[] args) {
		// demo1();
		// demo2();
		// demo3();
		// demo4();
		// demo5();
	}

	private static void demo5() {
		/*
		 * 测试
		 * 两个线程,一个调用类锁,一个调用普通的方法出现了
		 * ...
		 * 范坚强
		 * 范klz
		 * klz
		 * ...
		 * 所以必要时要把相应的代码锁起来,否则会出现这类情况
		 */
		Threads3 t3 = new Threads3();
		new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				while(true){
					t3.printer1();
				}
			}
		}.start();
		
		new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				while(true){
					t3.printer2();
				}
			}
		}.start();
	}
	
	public synchronized void printer1(){
		System.out.print("k");
		System.out.print("l");
		System.out.print("z");
		System.out.print("\r\n");
	}
	
	public static void printer2(){

		System.out.print("范");
		System.out.print("坚");
		System.out.print("强");
		System.out.print("\r\n");
		
	}

	private static void demo4() {
		/*
		 * 类锁与对象锁是不同的锁,是独立存在的
		 * 每个类虽然可以有多个静态的Synchronized 修饰的方法,但是只有一个类锁
		 * 由于静态方法是类所有对象共用的,所以进行同步后,该静态方法的锁也是所有对象唯一的。
		 * 使用两个线程调用同一个类锁,	一个获得后另一个线程必须等待 一个线程执行完毕后,另一个线程才开始执行
		 * 两个线程调,一个调用类锁,一个调用对象锁,线程的执行顺序是: 两个线程是交替执行的
		 */
		Threads3 t3 = new Threads3();
		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				t3.synchronized4();
			}
		}).start();

		new Thread() {
			public void run() {
//				t3.synchronized4();
				t3.synchronized1();
			};
		}.start();
	}

	private static void demo3() {
		/*
		 * 非静态方法的同步(对象锁) 因为在两个线程一个调用了Synchronized修饰的非静态方法,一个调用了普通的方法 两个线程交替执行
		 */
		Threads3 t3 = new Threads3();
		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				t3.synchronized1();
			}
		}).start();

		new Thread() {
			public void run() {
				t3.stander();
			};
		}.start();
	}

	private static void demo2() {
		/*
		 * 非静态方法的同步(对象锁) 因为在两个线程里面都调用了不同个Synchronized修饰的非静态方法
		 * 那么这两个线程都需要获得该对象锁,一个获得后另一个线程必须等待 一个线程执行完毕后,另一个线程才开始执行
		 */
		Threads3 t3 = new Threads3();
		Thread t1 = new Thread() {
			public void run() {
				t3.synchronized1();
			};
		};

		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				t3.synchronized2();
			}
		});

		t1.start();
		t2.start();
	}

	private static void demo1() {
		/*
		 * 非静态方法的同步(对象锁) 因为在两个线程里面都调用了同一个Synchronized修饰的非静态方法
		 * 那么这两个线程都需要获得该对象锁,一个获得后另一个线程必须等待 一个线程执行完毕后,另一个线程才开始执行
		 */
		Threads3 t3 = new Threads3();

		new Thread("klz") {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				t3.synchronized1();
			}
		}.start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				t3.synchronized1();
			}
		}).start();
	}

	/*
	 * 非静态方法使用 synchronized 修饰的写法,修饰实例方法时,锁定的是当前对象:
	 */
	public synchronized void synchronized1() {
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "aaa");
		}
	}

	/*
	 * 非静态方法使用 synchronized 修饰的写法,修饰实例方法时,锁定的是当前对象:
	 */
	public synchronized void synchronized2() {
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "bbb");
		}
	}

	/*
	 * 普通方法
	 */
	public void stander() {
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "ccc");
		}
	}

	/*
	 * 类锁需要 synchronized 来修饰静态 static 方法
	 */
	public static synchronized void synchronized4() {
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "ddd");
		}
	}

	/*
	 * 静态方法里面,同步代码块的对象为:类名.class 也称为类锁
	 */
	public static void synchronized5() {
		synchronized (Threads3.class) {
			// TODO
		}
	}
	
	/*
	 * 类锁需要 synchronized 来修饰静态 static 方法
	 */
	public static synchronized void synchronized6() {
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "eee");
		}
	}

}

// 单例模式 :懒汉模式(懒加载)
class Singleton {
	private Singleton() {
	}

	private static Singleton s = null;

	private static Singleton getInstance() {
		if (s == null) {
			synchronized (Singleton.class) {
				if (s == null) {
					s = new Singleton();
				}
			}
		}
		return s;
	}
}

发布了54 篇原创文章 · 获赞 0 · 访问量 343

猜你喜欢

转载自blog.csdn.net/qq_42977003/article/details/102988840