并发编程一:Synchronized的使用及分析
程序员文章站
2022-06-21 10:55:37
...
本文主要为了分析Synchronized的使用及分析,全程例子跟踪讲解,妈妈再也不用担心你的编程。(Lock等后续会讲解)
首先我们先看个例子:
public class MyThread implements Runnable{
// 定义一个变量
static int i=0;
// 方法 使内部变量 加加递增
public void add(){
i++;
}
// 实现Runnable重写线程run方法
@Override
public void run() {
for(int i=0;i<10000;i++){
add();
}
}
// 主函数 程序入口(我好像多余写,但是我就想写,怎样?)
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
// 创建一个线程 t1
Thread t1=new Thread(myThread);
// 创建一个线程 t2
Thread t2=new Thread(myThread);
// 启动线程
t1.start();
t2.start();
// join不知道的自己百度,简单解释下:调用join的线程必须执行完才能继续执行主线程,此处也可以用sleep
t1.join();t2.join();
System.out.printf("结果:"+i);
}
}
3次运行结果:
从结果上我们可以发现,有一次结果是正确的,俩次不正确。这就是线程不安全的。下面我们在add方法上添加synchronized再进行测试
public class MyThread implements Runnable{
// 定义一个变量
static int i=0;
// 方法 使内部变量 加加递增
public synchronized void add(){
i++;
}
// 实现Runnable重写线程run方法
@Override
public void run() {
for(int i=0;i<10000;i++){
add();
}
}
// 主函数 程序入口(我好像多余写,但是我就想写,怎样?)
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
// 创建一个线程 t1
Thread t1=new Thread(myThread);
// 创建一个线程 t2
Thread t2=new Thread(myThread);
// 启动线程
t1.start();
t2.start();
// join不知道的自己百度,简单解释下:调用join的线程必须执行完才能继续执行主线程,此处也可以用sleep
t1.join();t2.join();
System.out.printf("结果:"+i);
}
}
继续看3次运行结果:
哈哈哈 我们会发现 全都是 20000了,都是正确的结果。看来添加synchronized 可以保证线程的安全。你以为这就完事了,刚刚开始而已。来我们再来看个例子:
public class MyThread implements Runnable{
// 定义一个变量
static int i=0;
// 方法 使内部变量 加加递增
public synchronized void add(){
i++;
}
// 实现Runnable重写线程run方法
@Override
public void run() {
for(int i=0;i<10000;i++){
add();
}
}
// 主函数 程序入口(我好像多余写,但是我就想写,怎样?)
public static void main(String[] args) throws InterruptedException {
//MyThread myThread = new MyThread();
// 创建一个线程 t1
Thread t1=new Thread(new MyThread());
// 创建一个线程 t2
Thread t2=new Thread(new MyThread());
// 启动线程
t1.start();
t2.start();
// join不知道的自己百度,简单解释下:调用join的线程必须执行完才能继续执行主线程,此处也可以用sleep
t1.join();t2.join();
System.out.printf("结果:"+i);
}
}
这段代码add方法上也添加了synchronize,但是我们为每个线程创建了一个MyThread对象而不是上面的两个线程用一个对象。
下面继续看3次的运行结果:
卧槽了吧,哈哈怎么方法加了synchonized 线程还不安全。这里面就涉及到了对象锁和类锁的问题。有空再写吧写这玩意浪费时间。直接总结下吧 static synchonized和synchonized (类名.class) 可以解决问题 这俩都是类锁,类只有一个文件所以只能有一个线程获取到锁所以线程安全,至于对象锁也不是没用对象锁保证的是单个对象操作的并发问题
推荐阅读
-
Java并发编程中线程池源码分析及使用
-
mybatis的使用及源码分析(一) mybatis介绍以及原生Mybatis项目搭建
-
[java并发编程之深入理解]Synchronized的使用
-
Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析
-
Java并发编程深入理解之Synchronized的使用及底层原理详解 下
-
并发编程一:Synchronized的使用及分析
-
Java并发编程深入理解之Synchronized的使用及底层原理详解 上
-
Java并发编程中线程池源码分析及使用
-
Java高并发编程中ForkJoinPool的使用及详细介绍-刘宇
-
Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析