两种用法
对象锁
包括方法锁(默认锁对象为this当前对象实例)和同步代码块锁(自己指定锁对象)
类锁
指synchronized修饰的静态方法或指定锁为Class对象
对象锁-方法锁
public class SynchronizedObjectMethod3 implements Runnable {
static SynchronizedObjectMethod3 instance = new SynchronizedObjectMethod3();
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
// t1.join();
// t2.join();
while(t1.isAlive() || t2.isAlive()) {}
System.out.println("finished");
}
@Override
public void run() {
method();
}
public synchronized void method() {
System.out.println("I'm object method lock " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I'm object method lock " + Thread.currentThread().getName() + " is over");
}
}
对象锁-代码块
我们可以使用this来加锁,但可能一个类中不止一个代码段需要用到锁,我们希望它们是独立的,所有我们需要自己去定义一个对象,这个对象的作用就是充当锁的作用,它再无其它的任何含义(信号量机制里面的最简单的0/1互斥)
public class SynchronizedObjectCodeBlock2 implements Runnable {
static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
// t1.join();
// t2.join();
while(t1.isAlive() || t2.isAlive()) {}
System.out.println("finished");
}
@Override
public void run() {
synchronized (this) {
System.out.println("I'm object code block " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I'm object code block " + Thread.currentThread().getName() + " is over");
}
}
}
public class SynchronizedObjectCodeBlock2 implements Runnable {
static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
// t1.join();
// t2.join();
while(t1.isAlive() || t2.isAlive()) {}
System.out.println("finished");
}
@Override
public void run() {
synchronized (lock1) {
System.out.println("I'm object code block lock1 " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I'm object code block lock1 " + Thread.currentThread().getName() + " is over");
}
synchronized (lock2) {
System.out.println("I'm object code block lock2 " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I'm object code block lock2 " + Thread.currentThread().getName() + " is over");
}
}
}
再随着业务逻辑的复杂,手工用synchronized去实现并发也是有风险的,这种时候我们一般会使用框架。
类锁的概念
概念
只有一个类对象,Java类可能有很多对象,但只有一个Class对象(反射机制里面的类类型)
本质
所谓类锁:不过是Class对象的锁而已
它具有两种形式:
- synchronized加在static方法上
- synchronized(*.class)代码块
用法和效果
类锁只能在同一时刻被一个对象拥有(不同的Runnable实例只有一个类锁,这个之前的对象锁是不同的)
类锁-静态方法锁
其实静态方法锁相比于普通方法锁,多了一个static,static关键字在Java中本身就有“全局”的含义,它实现不同实例间同步也不难理解
public class SynchronizedStaticMethod4 implements Runnable {
static SynchronizedStaticMethod4 instance1 = new SynchronizedStaticMethod4();
static SynchronizedStaticMethod4 instance2 = new SynchronizedStaticMethod4();
public static void main(String[] args) {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
// t1.join();
// t2.join();
while(t1.isAlive() || t2.isAlive()) {}
System.out.println("finished");
}
@Override
public void run() {
method();
}
public static synchronized void method() {
System.out.println("I'm object method lock " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I'm object method lock " + Thread.currentThread().getName() + " is over");
}
}
代码对比对象锁-普通方法锁变化也就是两个Runnable实例,加锁的方法被static修饰。
类锁-*.class代码块
如果学习过Java的反射机制的话就会知道.class获取到的该类的类类型,这对于一个类创建的实例而言自然只有一个类类型,在类的层面来加锁也就实现了。
public class SynchronizedClassClass5 implements Runnable{
static SynchronizedClassClass5 instance1 = new SynchronizedClassClass5();
static SynchronizedClassClass5 instance2 = new SynchronizedClassClass5();
public static void main(String[] args) {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
// t1.join();
// t2.join();
while(t1.isAlive() || t2.isAlive()) {}
System.out.println("finished");
}
@Override
public void run() {
method();
}
public static synchronized void method() {
// 三种获取类类型的方式都是可以的
// synchronized (SynchronizedClassClass5.class) {
// synchronized (instance1.getClass()) {
Class c = null;
try {
c = Class.forName("com.nevercome.concurrency.SynchronizedClassClass5");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
synchronized (c) {
System.out.println("I'm object method lock " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I'm object method lock " + Thread.currentThread().getName() + " is over");
}
}
}