1. 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码块前要获得给定对象的锁,并且是在需要是同一个对象锁,也即创建实现Runnable接口的时候需要是同一个对象,如果创建了两个对象那么他们不属于同一个对象锁:
public class ThreadCount implements Runnable{
private static int count = 100;
@Override
public void run() {
while (true){
cal();
}
}
private void cal() {
if (count > 1){
// 加锁
synchronized (this){
count--;
System.out.println(Thread.currentThread().getName() + " " + count);
}
}
}
public static void main(String[] args) {
ThreadCount threadCount = new ThreadCount();
new Thread(threadCount).start();
new Thread(threadCount).start();
}
}
2. 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁:
package thread;
public class ThreadCount implements Runnable{
private static int count = 100;
@Override
public void run() {
while (true){
cal();
}
}
// 如果将synchronized加到实例方法上则使用this锁, 等同于之前的写法, 所以一般在方法上加上锁会比较方便一点
private synchronized void cal() {
if (count > 1){
count--;
System.out.println(Thread.currentThread().getName() + " " + count);
}
}
public static void main(String[] args) {
ThreadCount threadCount = new ThreadCount();
new Thread(threadCount).start();
new Thread(threadCount).start();
}
}
3. 如果将synchronized加到静态方法上,默认使用当前的类名.class:
package thread;
public class ThreadCount implements Runnable{
private static int count = 100;
@Override
public void run() {
while (true){
cal();
}
}
// 如果将synchronized加到静态方法上,默认使用当前的类名.class的锁
private void cal() {
synchronized(ThreadCount.class){
if (count > 1){
count--;
System.out.println(Thread.currentThread().getName() + " " + count);
}
}
}
public static void main(String[] args) {
ThreadCount threadCount = new ThreadCount();
new Thread(threadCount).start();
new Thread(threadCount).start();
}
}
4. 我们如果在使用 synchronized 需要注意 synchronized 锁嵌套的问题,避免死锁的问题发生,下面就是一个发生死锁的问题,线程1获取自定义的lock锁之后执行a()方法还需要获取this锁,线程2获取this锁之后执行b()方法还需要获取lock锁,当线程1和线程2在同时执行的时候,两个线程相互等待对方的锁释放一直在僵持那么就会造成死锁的问题:
package thread;
public class DeadLockThread implements Runnable{
private int count = 100;
private String lock = "lock";
@Override
public void run() {
// 发生死锁问题
while (true){
count ++;
if (count % 2 == 0){
// 线程1获取lock之后还需要获取a方法this锁
synchronized(lock){
a();
}
}else{
// 线程2获取this锁还需要获取b方法lock锁
synchronized (this){
b();
}
}
}
}
public void b() {
synchronized (lock){
System.out.println(Thread.currentThread().getName() + " b方法");
}
}
public synchronized void a() {
System.out.println(Thread.currentThread().getName() + " a方法");
}
public static void main(String[] args) {
DeadLockThread deadLockThread = new DeadLockThread();
Thread thread1 = new Thread(deadLockThread);
Thread thread2 = new Thread(deadLockThread);
thread1.start();
thread2.start();
}
}