锁能锁的东西只有两个,一个是new出来的对象, 另一个是Class模板,因为对象是由Class模板new出来的所以class模板也可以上锁
对象可以有多个,但class模板只有一个
1.执行下面这段代码,那个方法会先执行?
import java.util.concurrent.TimeUnit;
/**
* @Author : chenjianbo
* @Data : 2022/1/19 16:14
*/
public class SynchronizedTest {
public synchronized void eat(){
System.out.println("猫在吃东西");
}
public synchronized void sleep(){
System.out.println("猫在睡觉");
}
//主方法
public static void main(String[] args) throws InterruptedException {
SynchronizedTest cat = new SynchronizedTest();
//启动线程执行cat类的方法
new Thread(()->{
//执行方法
cat.eat();
},"A").start();
//执行完A线程以后 主线程睡眠几秒后在执行B线程
TimeUnit.SECONDS.sleep(2);
//启动线程执行cat类的方法
new Thread(()->{
cat.sleep();
},"B").start();
}
}
答:Synchronized锁的是方法的调用者也就是 cat这个实例。因为这两个线程调用的是同一个实例的方法,所以谁先调用谁就获得锁。
2.在线程中加入睡眠,输出的结果又是怎样
import java.util.concurrent.TimeUnit;
/**
* @Author : chenjianbo
* @Data : 2022/1/19 16:14
*/
public class SynchronizedTest {
public synchronized void eat(){
System.out.println("猫在吃东西");
}
public synchronized void sleep(){
System.out.println("猫在睡觉");
}
public static void main(String[] args) throws InterruptedException {
SynchronizedTest cat = new SynchronizedTest();
//启动线程执行cat类的方法
new Thread(()->{
//睡眠
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
//执行方法
cat.eat();
},"A").start();
//执行完A线程以后 主线程睡眠几秒后在执行B线程
TimeUnit.SECONDS.sleep(2);
//启动线程执行cat类的方法
new Thread(()->{
cat.sleep();
},"B").start();
}
}
答: 因为线程中睡眠的时间 超过了主线程中的睡眠时间,导致线程B中的sleep()方法首先获得了锁。
3.在eat()方法中加入睡眠,输出的结果又是怎样
import java.util.concurrent.TimeUnit;
/**
* @Author : chenjianbo
* @Data : 2022/1/19 16:14
*/
public class SynchronizedTest {
public synchronized void eat(){
//睡眠
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("猫在吃东西");
}
public synchronized void sleep(){
System.out.println("猫在睡觉");
}
public static void main(String[] args) throws InterruptedException {
SynchronizedTest cat = new SynchronizedTest();
//启动线程执行cat类的方法
new Thread(()->{
//执行方法
cat.eat();
},"A").start();
//执行完A线程以后 主线程睡眠几秒后在执行B线程
TimeUnit.SECONDS.sleep(2);
//启动线程执行cat类的方法
new Thread(()->{
cat.sleep();
},"B").start();
}
}
答:虽然eat()方法中有睡眠 但还是eat()方法先获得了锁,只有等eat()方法执行完 另一个方法才能获取到锁
4.把sleep()方法改成普通类,不再用synchronized修饰,结果会怎样
import java.util.concurrent.TimeUnit;
/**
* @Author : chenjianbo
* @Data : 2022/1/19 16:14
*/
public class SynchronizedTest {
public synchronized void eat(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("猫在吃东西");
}
public void sleep(){
System.out.println("猫在睡觉");
}
public static void main(String[] args) throws InterruptedException {
SynchronizedTest cat = new SynchronizedTest();
//启动线程执行cat类的方法
new Thread(()->{
//执行方法
cat.eat();
},"A").start();
//执行完A线程以后 主线程睡眠几秒后在执行B线程
TimeUnit.SECONDS.sleep(2);
//启动线程执行cat类的方法
new Thread(()->{
cat.sleep();
},"B").start();
}
}
答:因为sleep()方法是普通类没有锁,不受锁的影响,那么这两个线程之间没有关系,各自运行。但因为eat()方法中有睡眠,且大于主线程中的睡眠时间,所以线程B中的内容会先输出来
5.实例化两个类,两个同步方法,结果又如何?
import java.util.concurrent.TimeUnit;
/**
* @Author : chenjianbo
* @Data : 2022/1/19 16:14
*/
public class SynchronizedTest {
public synchronized void eat(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("猫在吃东西");
}
public synchronized void sleep(){
System.out.println("猫在睡觉");
}
public static void main(String[] args) throws InterruptedException {
SynchronizedTest cat = new SynchronizedTest();
SynchronizedTest cat2 = new SynchronizedTest();
//启动线程执行cat类的方法
new Thread(()->{
//执行方法
cat.eat();
},"A").start();
//执行完A线程以后 主线程睡眠几秒后在执行B线程
TimeUnit.SECONDS.sleep(2);
//启动线程执行cat类的方法
new Thread(()->{
cat2.sleep();
},"B").start();
}
}
答:因为是两个实例化的对象,锁的是各自的对象,也就是有两把锁,两个线程之间没有联系,因为A线程中eat()方法中的睡眠时间大于主线程中的睡眠时间,所以B线程中的内容会先输出出来
6.把两个方法变成静态方法,那结果又该如何
import java.util.concurrent.TimeUnit;
/**
* @Author : chenjianbo
* @Data : 2022/1/19 16:14
*/
public class SynchronizedTest {
public static synchronized void eat(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("猫在吃东西");
}
public static synchronized void sleep(){
System.out.println("猫在睡觉");
}
public static void main(String[] args) throws InterruptedException {
//启动线程执行cat类的方法
new Thread(()->{
//执行方法
SynchronizedTest.eat();
},"A").start();
//执行完A线程以后 主线程睡眠几秒后在执行B线程
TimeUnit.SECONDS.sleep(2);
//启动线程执行cat类的方法
new Thread(()->{
SynchronizedTest.sleep();
},"B").start();
}
}
回答:静态方法在类加载的时候就已经生成了,所以synchronized锁的不再是对象 而是Class模板,因为Class模板只有一个所以这两个方法用的是同一个锁,所以谁先获取到锁就先执行谁。
7.一个设置成静态方法,一个同步方法,结果如何
import java.util.concurrent.TimeUnit;
/**
* @Author : chenjianbo
* @Data : 2022/1/19 16:14
*/
public class SynchronizedTest {
public static synchronized void eat(){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("猫在吃东西");
}
public synchronized void sleep(){
System.out.println("猫在睡觉");
}
public static void main(String[] args) throws InterruptedException {
SynchronizedTest cat = new SynchronizedTest();
//启动线程执行cat类的方法
new Thread(()->{
//执行方法
SynchronizedTest.eat();
},"A").start();
//执行完A线程以后 主线程睡眠几秒后在执行B线程
TimeUnit.SECONDS.sleep(2);
//启动线程执行cat类的方法
new Thread(()->{
cat.sleep();
},"B").start();
}
}
答:static synchronized 锁的是对象,synchronized 锁的是Class模板,两者锁的东西不一样即有两个锁,两个线程之间没有关系,虽然A线程中的方法有睡眠 但睡眠时间短于主线程睡眠的时间,所以A线程的内容会先输出出来。