synchronized关键字的详细分析和代码实例
在Java中,一般都是通过同步机制来解决线程安全问题的,在JDK 5.0之后又新增了Lock的方式来实现线程安全。所以说实现线程安全方式一共有三种方法
方式一:
synchronized(同步监视器){
//需要被同步的代码(操作共享数据的代码就是需要被同步的代码)
}
通过继承Thread类的方式实现多线程并解决线程安全问题:
package com.baozi.java;
public class WinowTest {
public static void main(String[] args){
Window w1=new Window();
Window w2=new Window();
Window w3=new Window();
w1.start();
w2.start();
w3.start();
}
}
//通过继承Thread类的方法来实现多线程
class Window extends Thread {
private static int ticket = 100;
@Override
public void run() {
while (true) {
//这里通过synchronized代码块的形式来实现线程安全
synchronized (Window.class) {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
}
}
通过实现Runnable接口的方式实现多线程并解决线程安全问题:
package com.baozi.java;
public class WindowTest2 {
public static void main(String[] args){
Window2 window2 = new Window2();
Thread t1 = new Thread(window2);
Thread t2 = new Thread(window2);
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
//通过实现Runnable接口的方式实现多线程
class Window2 implements Runnable{
private int ticket = 100;
@Override
public void run() {
while (true) {
//这里通过synchronized代码块的形式来实现线程安全
synchronized (this) {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
}
}
备注:
同步监视器:其实就是我们平时说的锁,任何一个类对象都可以充当同步监视器,并且针对需要操作的共享数据,要求多个线程必须共享同一个同步监视器,这样才能实现多线程共享数据的线程安全。
同步方法解决了线程安全问题,但是在操作同步代码块的时候,实质上某一时刻只有一个线程拥有锁,其他线程需要操作共享数据的时候只能等待该线程释放了所之后通过抢占方式获得锁之后才能执行。言外之意针对共享数据其实是单线程执行,这样会造成效率非常低。
方式二:
如果多个线程操作的共享数据的代码完整的声明在一个方法中,那么我们使用synchronized关键字修饰这个方法为同步方法。
通过继承Thread类的方式实现多线程并解决线程安全问题:
package com.baozi.java;
public class WindowTest3 {
public static void main(String[] args) {
Window3 w1 = new Window3();
Window3 w2 = new Window3();
Window3 w3 = new Window3();
w1.start();
w2.start();
w3.start();
}
}
//通过继承Thread类的方法来实现多线程
class Window3 extends Thread {
private static int ticket = 100;
@Override
public void run() {
while (true) {
show();
}
}
//这里通过synchronized方法的形式来实现线程安全
public static synchronized void show() {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
}
}
通过实现Runnable接口的方式实现多线程并解决线程安全问题:
package com.baozi.java;
public class WindowTest2 {
public static void main(String[] args) {
Window2 window2 = new Window2();
Thread t1 = new Thread(window2);
Thread t2 = new Thread(window2);
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
//通过实现Runnable接口的方式实现多线程
class Window2 implements Runnable {
private int ticket = 100;
@Override
public synchronized void run() {
while (true) {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
}
备注:同步方法依然会涉及到同步监视器,只是不需要我么显示的声明。
非静态的同步方法:同步监视器可以是this(当前对象)
静态的同步方法:同步监视器可以是当前类
这样我们就能省去单独造一个对象来充当同步监视器,使代码比较简单整洁。
方式三:
使用Lock锁的方式实现线程安全,这是JDK5.0新增加的方法,在后边单独分析。
synchronized关键字的详细分析和代码实例的更多相关文章
- Java:多线程,线程同步,synchronized关键字的用法(同步代码块、非静态同步方法、静态同步方法)
关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨synchronized关键字. sy ...
- 【智能算法】粒子群算法(Particle Swarm Optimization)超详细解析+入门代码实例讲解
喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 算法起源 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由E ...
- Java精通并发-Lock与synchronized关键字在底层的区别及实例分析
在上两次中已经将Lock这个接口的整个官方说明进行了阅读,这次来了解一下它的一个非常重要的实现类: 啥叫“可重入”呢?其实是指一个线程已经拿到了锁,然后该线程还能再次获取这把锁,接下来在了解它之前先用 ...
- java动态代理实现与原理详细分析(代码层面解释了AOP的实现)
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式 代理模式是常用的java设计模式, ...
- Apriori算法第二篇----详细分析和代码实现
1 Apriori介绍 Apriori算法使用频繁项集的先验知识,使用一种称作逐层搜索的迭代方法,k项集用于探索(k+1)项集.首先,通过扫描事务(交易)记录,找出所有的频繁1项集,该集合记做L1,然 ...
- Spring 注解详细分析解释有实例
概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...
- hibernate缓存机制详细分析 复制代码 内部资料 请勿转载 谢谢合作
您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内 ...
- 管理后台界面 详细分析(内含代码 |【前端】)RuoYi
最近在做的一个后台管理 因为关于隐私原因 只方便展示个别页面代码 不会上传项目 注意是前端代码 我把项目代码地址放在最后了 如有需要可自取学习 我会为各位兄弟详细的介绍其中各个属性的含义和用法,记 ...
- Java精通并发-透过字节码理解synchronized关键字
在上一次https://www.cnblogs.com/webor2006/p/11428408.html中对于synchronized关键字的作用做了一个实例详解,下面再来看一下这个程序: 请问下, ...
随机推荐
- jenkins启动
1.已安装JDK,因为jenkins是一款基于java的持续集成工具 2.已配置tomcat,并安装maven 3.下载一个jenkins的war包,放在tomcat/webapps目录下 4.cmd ...
- 一、下载安装superset
1.环境介绍: 操作系统:Windows 10 python版本:3.73 2.创建虚拟环境: 打开命令行窗口,使用安装python自带的pip命令,下载pinenv 虚拟环境工具, pip inst ...
- Arduino语言简介
参考链接:https://www.cnblogs.com/xczr/p/7831343.html
- 「luogu4462」[CQOI2018] 异或序列
「luogu4462」[CQOI2018]异或序列 一句话题意 输入 \(n\) 个数,给定\(k\),共 \(m\) 组询问,输出第 \(i\) 组询问 \(l_i\) \(r_i\) 中有多少个连 ...
- 找到多个与名为“Home”的控制器匹配的类型。解决方法
“/”应用程序中的服务器错误. 找到多个与名为“Home”的控制器匹配的类型.如果为此请求(“{controller}/{action}/{id}”)提供服务的路由没有指定命名空间以搜索与此请求相匹配 ...
- SSH整合 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- mybatis调用oracle存储过程的几个参考例子
首先写一个存储过程: create or replace procedure p_syn_equipment_20161205 is sqlstr ); begin --清空表 sqlstr := ' ...
- LaTex basics
分节: \section{Supplemental Material}\label{sec:supplemental} 小节: \noindent {\bf Preparing References: ...
- Gitlab_ansible_jenkins三剑客⑥Jenkins和ansible集成
ip 角色 备注 10.11.0.215 jenkins服务器 通过deploy运行jenkins服务,deploy用户做了免秘钥登录ansible服务器 10.11.0.210 ansible服务器 ...
- 高可用Redis(一):通用命令,数据结构和内部编码,单线程架构
1.通用API 1.1 keys命令和dbsize命令 keys * 遍历所有key keys [pattern] 遍历模式下所有的key dbsize 计算Redis中所有key的总数 例子: 12 ...