在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关键字的详细分析和代码实例的更多相关文章

  1. Java:多线程,线程同步,synchronized关键字的用法(同步代码块、非静态同步方法、静态同步方法)

    关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨synchronized关键字. sy ...

  2. 【智能算法】粒子群算法(Particle Swarm Optimization)超详细解析+入门代码实例讲解

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 算法起源 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由E ...

  3. Java精通并发-Lock与synchronized关键字在底层的区别及实例分析

    在上两次中已经将Lock这个接口的整个官方说明进行了阅读,这次来了解一下它的一个非常重要的实现类: 啥叫“可重入”呢?其实是指一个线程已经拿到了锁,然后该线程还能再次获取这把锁,接下来在了解它之前先用 ...

  4. java动态代理实现与原理详细分析(代码层面解释了AOP的实现)

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...

  5. Apriori算法第二篇----详细分析和代码实现

    1 Apriori介绍 Apriori算法使用频繁项集的先验知识,使用一种称作逐层搜索的迭代方法,k项集用于探索(k+1)项集.首先,通过扫描事务(交易)记录,找出所有的频繁1项集,该集合记做L1,然 ...

  6. Spring 注解详细分析解释有实例

    概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...

  7. hibernate缓存机制详细分析 复制代码 内部资料 请勿转载 谢谢合作

    您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内 ...

  8. 管理后台界面 详细分析(内含代码 |【前端】)RuoYi

    最近在做的一个后台管理 因为关于隐私原因 只方便展示个别页面代码 不会上传项目 注意是前端代码 我把项目代码地址放在最后了 如有需要可自取学习   我会为各位兄弟详细的介绍其中各个属性的含义和用法,记 ...

  9. Java精通并发-透过字节码理解synchronized关键字

    在上一次https://www.cnblogs.com/webor2006/p/11428408.html中对于synchronized关键字的作用做了一个实例详解,下面再来看一下这个程序: 请问下, ...

随机推荐

  1. windows查看进程信息

    wmic process where caption="java.exe" get processid,caption,commandline /value

  2. 论文翻译——Lattice indexing for spoken term detection

    第II节简要介绍与本文有关的先前工作第III节介绍文中使用的定义以及术语 第IV节介绍如何从原始ASR lattices中生成倒排索引结构 第V节详细介绍了ASR结构以及实验使用的数据 第VI节提供了 ...

  3. proxysql系列 ~ 运维相关

    一 常用命令   //实时加载   load mysql servers to runtime; mysql_server   load mysql users to runtime; mysql_u ...

  4. QT windeployqt

    qt发布release版本时需要打包一些dll,需要哪些呢?请看截图: 在qt的安装包下找到这些文件,放在release文件夹下即可,当然有些时候也会需要一些其他的,比如含有串口的程序还需要加入Qt5 ...

  5. docker镜像常用操作

  6. Angular 项目列表页

    $ ng g m project 功能:项目列表显示,增加,修改,删除项目.邀请其它人员加入项目. 单一性原则:希望搭建多个组件,每个组件负责自己的功能. 一.project相关组件 $ ng g c ...

  7. MAC Undefined symbols for architecture x86_64 cv::imwrite

    因为homebrew安装opencv时用的是clang,而CLion中使用的是gcc编译器. 将clion中的编译器改回默认的clang就行了.

  8. python中用xlsxwriter创建图表

    缺点:xlsxwriter不能对已存在的Excel进行编辑插入图标   生成图标需要: 1.先准备数据 2.将数据插入到excel中 3.根据插入的数据生成图表 这里的生成excel主要分为准备多维数 ...

  9. Imcash:一边大裁员,一边大扩招,你能否成为区块链人才中的7%?

    农历春节后,互联网创业圈并不太平. 最早,滴滴被曝裁员,占比约为全员的15%,涉及员工约2000人.CEO程维在全员会议上称公司要做好过冬准备.此后,京东接棒,其裁员对象上升至副总裁级别高管,比例占到 ...

  10. notes for lxf(三)

    纯函数式编程是没有变量的,只要输入确定输出就确定 指高度抽象的编程范式 特点 函数本身可以作为参数传入 或者允许返回一个函数 Higher-order function 一个函数可以接收另一个函数作为 ...