1.Synchronized: 只可以锁对象(如果加在方法上,意思是锁住当前类对象this)。当一个线程执行到该关键字时,若其他线程也要访问该共享资源,那么其他线程进入Block状态。 其中test为共享资源。
若Thread1在执行synchronized块时,时间片用完,那么它就退出synchronized块,处于就绪状态(这时共享资源仍被锁着),与thread2一起竞争时间片。当时间片分给thread2时,thread2没有synchronized的钥匙,不能继续执行,所以又处于block状态;当时间片分给thread1后,thread1 进入synchronized块继续执行未完成的code。当synchronized的code被执行完后就释放锁,并唤醒被Block的线程。
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "TC5")
public class TC5 {
static Object test = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (test) {
log.debug("only thread1 can access it.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (test) {
log.debug("only thread2 can access it.");
}
});
thread1.start();
thread2.start();
log.debug("Thread1的状态:"+thread1.getState());
log.debug("Thread2的状态:"+thread2.getState());
}
}
2.synchronized加在成员方法上锁住this对象,synchronized加在静态方法上锁住类名.class对象。
a方法锁的是类对象,b方法锁的是this对象,所以锁的是不同的对象;因此他们之间没有互斥关系,两个线程可以并行执行。
都锁住类对象,所以n1.a()和n2.b()是互斥的:
import lombok.extern.slf4j.Slf4j;
import java.util.Random;
@Slf4j(topic = "TC7")
public class TC7 {
public static void main(String[] args) throws InterruptedException {
Account account1 = new Account(1000);
Account account2 = new Account(1000);
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
account1.transfer(account2,getRandomValue());
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
account2.transfer(account1,getRandomValue());
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
log.debug("两个账户总金额:{}",account1.getAccount()+account2.getAccount());
}
static Random random = new Random();
public static int getRandomValue() { return random.nextInt(5)+1;}
}
class Account{
private int account;
public Account(int account) {
this.account = account;
}
public void setAccount(int account) {
this.account=account;
}
public int getAccount() { return this.account;}
public int transfer(Account target, int amount) {
synchronized (Account.class) {
if (this.account>=amount) {
//线程共享this.account 和 target.account变量,因此要锁住这两个变量;
//如果给该方法加synchronized,只是给this.class加了锁,target.account没有控制住
//所以要给Account.class加锁,是this和target均被控制
this.setAccount(this.getAccount()-amount);
target.setAccount(target.getAccount()+amount);
return amount;
}else {
return 0;
}
}
}
}