一、总结
使用锁是Java中解决线程安全问题最主要的手段。
二、Java中的两种锁
Java中的锁主要有以下两种:
1.内置锁:synchronized
2.可重入锁:Lock(ReentrantLock)
三、synchronized用法
- 修饰静态方法
- 修饰普通方法
- 修饰代码块
1.修饰静态方法:
首先我们来看第一种方法;
那么我们先来回顾一下之前我们遗留的问题,使用synchronize的第一种用法去解决。
从下面的代码中可以看出我们只是将两个静态方法用synchronized去修饰,从执行结果可以看出来我们的问题解决了。
代码如下:
package thread.threaddemo;
/**
* @Author: wenjingyuan
* @Date: 2022/11/18/17:04
* @Description:
*/
public class ThreadSynchronized {
private static int number=0;
//定义一个内部类
static class Counter{
private static int MAX_Counter=100000;
public synchronized static void incr(){
for (int i = 0; i < MAX_Counter; i++) {
number++;
}
}
public synchronized static void decr(){
for (int i = 0; i < MAX_Counter; i++) {
number--;
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(()->{
Counter.incr();
});
t1.start();
Thread t2=new Thread(()->{
Counter.decr();
});
t2.start();
t1.join();
t2.join();
System.out.println("最终的结果"+ number);
}
}
执行结果:
缺点:
通过以上的示例我们可以看出来我们使用synchronized以后程序的性能会变慢,所以我们的程序性能的好坏取决于synchronized修饰的范围,synchronized修饰的范围越大,安全性就会越高,性能就会越低,锁的粒度越小,也就是修饰的代码越少,性能就会越高。
2.修饰普通方法
3.修饰代码块
修饰代码块时注意事项:
1.当使用synchronized一定要注意,对于同一个业务的多个线程加锁对象,一定要是同一个对象(也就是加同一把锁);
2.synchronized修饰代码块,代码块在静态方法中,不能使用this对象。这个时候可以是使用类.class。、
3.我们还可以自定义锁对象
四、synchronized特性
-
互斥性
某个线程执行到某个对象的synchronized中时,其他线程如果也执行到同一个对象的synchronized就会阻塞等待
-
刷新内存
解决内存可见性问题
-
可重入性
解释如下