synchronized加锁大概分为两类:(简介)
对象锁:包括方法锁(直接加在方法上,默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)【这是每个对象独有的,不同对象互相不影响】
类锁:指定synchronized修饰静态的方法(static方法)或指定锁的对象为class对象【这是给类的class对象加锁,是其他对象共用的类锁】



下面介绍详细用法:

对象锁:【注意:由于是对象锁,所以一下实例的多个线程引用的都是同一个对象,如果是不同对象那就不会有影响】

一、同步代码块

1、锁定当前对象this

package test_Synchronize;

public class SynchronizedObectCodeBlock implements Runnable{
	static SynchronizedObectCodeBlock instance = new SynchronizedObectCodeBlock();
	 
	public static void main(String[] args) throws InterruptedException {
                //引用同一个对象
		Thread th1 = new Thread(instance,"线程1");
		Thread th2 = new Thread(instance,"线程2");
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {
		}
		System.out.println("finished");
	}
 
	@Override
	public void run() {
		synchronized (this) {
 
			// Thread.currentThread()当前线程,.getName()名字
			System.out.println("我是对象锁的代码块形式我叫" + Thread.currentThread().getName());
			try {
				// 让线程休眠3秒
				Thread.sleep(3000);
				System.out.println("线程休息三秒后");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
 
			System.out.println(Thread.currentThread().getName() + "运行结束");
		}
	}
}
输出结果:
当把同步代码注释掉后的结果为:


2、锁定不同的对象
package test_Synchronize;

public class SynchronizedObectCodeBlock implements Runnable{
	static SynchronizedObectCodeBlock instance = new SynchronizedObectCodeBlock();
	Object lock1=new Object();
	Object lock2=new Object();
	 
	public static void main(String[] args) throws InterruptedException {
		Thread th1 = new Thread(instance,"线程1");
		Thread th2 = new Thread(instance,"线程2");
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {
		}
		System.out.println("finished");
	}
 
	@Override
	public void run() {
		synchronized (lock1) {
 
			// Thread.currentThread()当前线程,.getName()名字
			System.out.println("我是lock1对象锁的代码块形式我叫" + Thread.currentThread().getName());
			try {
				// 让线程休眠3秒
				Thread.sleep(3000);
				System.out.println("lock1锁-"+Thread.currentThread().getName()+"休息三秒后");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
 
			System.out.println("lock1锁-"+Thread.currentThread().getName() + "运行结束");
		}
		
		synchronized (lock2) {
			 
			// Thread.currentThread()当前线程,.getName()名字
			System.out.println("我是lock2对象锁的代码块形式我叫" + Thread.currentThread().getName());
			try {
				// 让线程休眠3秒
				Thread.sleep(3000);
				System.out.println("lock2锁-"+Thread.currentThread().getName()+"休息三秒后");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
 
			System.out.println("lock2锁-"+Thread.currentThread().getName() + "运行结束");
		}
	}
}

运行结果:
解析:因为lock1和lock2是在线程中都是lock1先行再执行lock2,所以是按顺序运行的,也就是lock1完成后才会走lock2,而不同线程是会争同一个lock1锁的,所以必须一个线程的lock1锁释放后另一个线程才能运行。且4、5行是同时运行的,因为此时一个线程拿的是lock1锁,一个拿的是lock2锁,互不影响,所以是并行的。

二、方法锁:只能修饰普通方法,对象默认是this

package test_Synchronize;

public class SynchronizedObjectMethod implements Runnable{
	static SynchronizedObjectMethod intance=new SynchronizedObjectMethod();
	public static void main(String[] args) {
                //【注意,线程引用的是同一个对象】
		Thread th1=new Thread(intance,"线程1");
		Thread th2=new Thread(intance,"线程2");
		th1.start();
		th2.start();
		while(th1.isAlive() || th2.isAlive()){
		}

		System.out.println("finished");
	}
	public void run() {
		method();
	}
	public synchronized void method(){
		System.out.println("我是对象锁的方法修饰符形式,我叫:"+Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"结束");
	}
}

运行结果:
(与同步代码块中锁定同一个对象的原理是一样的)


类锁【不同于对象锁,以下线程引用的是不同的对象】

概念:
a、只有一个class对象:java类可能会有很多个对象,但是只有1个class对象。【class类是java中存在的,class对象存放你自己写的类的所有信息,class对象保存在.class字节码文件中】
b、本质:所以所谓的类锁,不过是class对象的锁而已。
c、用法和效果:类锁只能在同一时刻被一个对象拥有

一、synchronize加在static方法上。

package test_Synchronize;

public class SynchronizedClassStatic implements Runnable{
	static SynchronizedClassStatic instance1 = new SynchronizedClassStatic();
	static SynchronizedClassStatic instance2 = new SynchronizedClassStatic();
 
	public static void main(String[] args) {
		Thread th1 = new Thread(instance1,"线程1");
		Thread th2 = new Thread(instance2,"线程2");
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {
 
		}
		System.out.println("finished");
	}
 
	public void run() {
		method();
	}
 
	public static synchronized void method(){
	System.out.println("我是类锁的第一种形式,static形式,我叫:"+Thread.currentThread().getName());
	try {
		Thread.sleep(3000);
		System.out.println(Thread.currentThread().getName()+"三秒后");
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	System.out.println(Thread.currentThread().getName()+"结束");
	}
}

运行结果:

如果去掉了static的运行结果:
因为去掉了static就变成了对象锁,只对同一对象生效

二、synchronize(*.class)代码块

.class表示用字面常量的方式获取Class对象的引用
package test_Synchronize;

public class SynchronizeClassClass implements Runnable {
	static SynchronizeClassClass instanec = new SynchronizeClassClass();
	static SynchronizeClassClass instanec2 = new SynchronizeClassClass();
 
	public static void main(String[] args) {
		Thread th1 = new Thread(instanec,"线程1");
		Thread th2 = new Thread(instanec2,"线程2");
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {
		}
		System.out.println("finished");
	}
 
	@Override
	public void run() {
		method();
	}
	private void method() {
		synchronized (SynchronizeClassClass.class) {
			System.out.println("我是类锁的第二种形式,synchronize(*.class),我叫" + Thread.currentThread().getName());
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"结束");
		}
	}
}

运行结果:

若把synchronized (SynchronizeClassClass.class)改成synchronized (this),结果为: