synchronized对象锁
package com.hanyxx.thread;
import lombok.SneakyThrows;
/**
* synchronized关键字会锁住整个对象中被synchronized修饰的方法。
* 运行结果:methodOne方法执行,2秒后,methodTwo方法执行
* @author layman
* @date 2021/2/5
*/
public class Demo06 {
public static void main(String[] args) {
Demo06Service service = new Demo06Service();
Demo06ThreadA threadA = new Demo06ThreadA(service);
Demo06ThreadB threadB = new Demo06ThreadB(service);
threadA.start();
threadB.start();
}
}
class Demo06Service{
@SneakyThrows
public synchronized void methodOne(){
System.out.println("methodOne方法执行");
Thread.sleep(2000);
}
@SneakyThrows
public synchronized void methodTwo(){
System.out.println("methodTwo方法执行");
Thread.sleep(2000);
}
}
class Demo06ThreadA extends Thread{
private Demo06Service service;
public Demo06ThreadA(Demo06Service service){
this.service = service;
}
@Override
public void run() {
service.methodOne();
}
}class Demo06ThreadB extends Thread{
private Demo06Service service;
public Demo06ThreadB(Demo06Service service){
this.service = service;
}
@Override
public void run() {
service.methodTwo();
}
}
结论:
脏读
package com.hanyxx.thread;
import lombok.SneakyThrows;
/**
* 模拟线程不同步导致脏读问题
* @author layman
* @date 2021/2/5
*/
public class Demo07 {
public static void main(String[] args) throws InterruptedException {
UserService service = new UserService();
Demo07Thread thread = new Demo07Thread(service);
thread.start();
Thread.sleep(500);
service.getValue();
}
}
class UserService{
private String username = "layman";
private String password = "12345";
@SneakyThrows
public void change(String username, String password){
this.username = username;
Thread.sleep(1000);
this.password = password;
System.out.println("线程名称:["+Thread.currentThread().getName()+"] ,change方法执行,username: "+username+" ,password: "+password);
}
public void getValue(){
System.out.println("线程名称:["+Thread.currentThread().getName()+"] ,getValue方法执行,username: "+username+" ,password: "+password);
}
}
class Demo07Thread extends Thread{
private UserService service;
public Demo07Thread(UserService service){
this.service = service;
}
@Override
public void run() {
service.change("菠菜饭团","54321");
}
}
解决方法:
- change()和getValue()都用synchronized修饰。
锁重入
- 关键字synchronized拥有锁重入功能,就是说在使用synchronized时,当一个线程得到一个对象锁时,再次请求这个对象时,可以再次获得该对象锁。
- 锁重入支持父子类继承。
package com.hanyxx.thread;
/**
* 测试锁重入以及父子继承
* @author layman
* @date 2021/2/5
*/
public class Demo08 {
public static void main(String[] args) {
new Demo08Thread().start();
}
}
class Demo08Service{
public synchronized void methodA() {
System.out.println("methodA方法执行了");
methodB();
}
public synchronized void methodB() {
System.out.println("methodB方法执行了");
methodC();
}
public synchronized void methodC() {
System.out.println("methodC方法执行了");
}
}
//锁重入支持父子继承
class Demo08ServiceA extends Demo08Service{
public synchronized void methodD() {
System.out.println("methodD方法执行了");
methodA();
}
}
class Demo08Thread extends Thread{
@Override
public void run() {
/*Demo08Service service = new Demo08Service();
service.methodA();*/
Demo08ServiceA service = new Demo08ServiceA();
service.methodD();
}
}