1.首先,什么是线程安全问题?
当多线程同时对同一个全局变量做 '写' 的操作的时候,可能会收到其他的线程的干扰,这个时候就容易发生线程的安全性问题。
2.如何解决线程安全的问题呢?
解决线程安全的问题的核心思想就是上锁,用的较多的应该是(synchronized)锁吧。
那么呢,在同一个jvm当中,当多个线程需要竞争锁的资源的时候,最后只能有一个线程能获取到这把锁,那现在就是哪个线程抢的快,抢到了就能够执行到该代码,那没有获取到锁的呢(也就是没有抢到锁的),它中间就需要经历锁的升级过程(后面可能会讲,也有可能就给个图,也有可能在下一篇文章里),如果没有获取到锁就会一直阻塞等待,
举个栗子:比如现在线程A获取到了锁,但是线程A一直不释放锁
那现在线程B就会一直获取不到锁,那就会一直阻塞等待(说白了就是不动了)
3.上锁的位置
那当然就是在可能发生线程安全的地方上锁辣,不然如果你整个代码都上锁或者一大片都上锁,那不是会降低代码的执行效率吗
4.synchronized锁的基本用法
在多线程的情况下: 需要是同一个对象锁
synchronized(对象锁)
{
可能发生多线程安全的代码
}
其中: 1) 如果将synchronized修饰静态方法,作用于当前类对象(当前类.class)加锁,进入同步代码前要后去当前的对象的锁(写法就是 synchronized(当前类.class))
2) 如果将synchronized修饰实例方法,作用于当前实例加锁,进入同步代码前要获取 当前实例的锁
3)如果将synchronized修饰代码块,指定加锁对象,对给定对象加锁(this锁),进入同步代码块前要获得 给定对象 的锁(也就是this锁)
1.修饰静态方法
package SyncCodInstance;
/**
* @BelongsProject: threads
* @BelongsPackage: SyncCodInstance
* @Author: 晚风
* @CreateTime: 2023-03-04 15:27
* @Description: TODO
* @Version: 1.0
*/
public class ModifyStaticMethods implements Runnable{
private static Integer count = 100;
@Override
public void run() {
while (count >1){
val();
}
}
private static void val(){
synchronized (ModifyStaticMethods.class){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "--" + count);
}
}
public static void main(String[] args) {
// modifyStaticMethods1 的意思是修饰静态方法
ModifyStaticMethods modifyStaticMethods1 = new ModifyStaticMethods();
ModifyStaticMethods modifyStaticMethods2 = new ModifyStaticMethods();
Thread thread1 = new Thread(modifyStaticMethods1);
Thread thread2 = new Thread(modifyStaticMethods2);
thread1.start();
thread2.start();
}
}
结果如下:(从100到0都是没有重复的)
2.修饰实例方法
package SyncCodInstance;
/**
* @BelongsProject: threads
* @BelongsPackage: SyncCodInstance
* @Author: 晚风
* @CreateTime: 2023-03-04 15:27
* @Description: TODO
* @Version: 1.0
*/
public class ModifyStaticMethods implements Runnable{
private static Integer count = 100;
@Override
public void run() {
while (count >1){
val();
}
}
private synchronized void val(){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "--" + count);
}
public static void main(String[] args) {
// modifyStaticMethods1 的意思是修饰静态方法
// ModifyStaticMethods modifyStaticMethods1 = new ModifyStaticMethods();
// ModifyStaticMethods modifyStaticMethods2 = new ModifyStaticMethods();
ModifyStaticMethods modifyStaticMethods = new ModifyStaticMethods();
Thread thread1 = new Thread(modifyStaticMethods);
Thread thread2 = new Thread(modifyStaticMethods);
thread1.start();
thread2.start();
}
}
结果如下:(和上面一样嗷)
修饰代码块
package SyncCodInstance;
/**
* @BelongsProject: threads
* @BelongsPackage: SyncCodInstance
* @Author: 晚风
* @CreateTime: 2023-03-04 15:27
* @Description: TODO
* @Version: 1.0
*/
public class ModifyStaticMethods implements Runnable{
private static Integer count = 100;
@Override
public void run() {
while (count >1){
val();
}
}
private void val(){
synchronized (this) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "--" + count);
}
}
public static void main(String[] args) {
// modifyStaticMethods1 的意思是修饰静态方法
// ModifyStaticMethods modifyStaticMethods1 = new ModifyStaticMethods();
// ModifyStaticMethods modifyStaticMethods2 = new ModifyStaticMethods();
ModifyStaticMethods modifyStaticMethods = new ModifyStaticMethods();
Thread thread1 = new Thread(modifyStaticMethods);
Thread thread2 = new Thread(modifyStaticMethods);
thread1.start();
thread2.start();
}
}
结果如下:(还是和上面一样嗷)
/*
*同学们注意这三个代码的synchronized()位置
*/
(都是看的课程里面,最后总结和课程里面的知识)
(为了防止犯法,看的是余胜军老师的课,这里标注,上课之后整理的东西然后写的博客)