在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. 多个div实现随意拖拽功能

    鼠标事件 mousedownmousemovemouseup注意事项:被拖动的div的position属性值一定是absolute.切记不可使用margin-top:10px;而应该使用top:10p ...

  2. day 18 - 2 正则与 re 模块练习

    1.爬虫的例子 #爬虫的例子(方法一) import re import urllib,request import urlopen def getPage(url): response = urlo ...

  3. android shape 圆圈 圆环 圆角

    定义圆圈:比如角标: xml布局文件 <TextView android:id="@+id/item_order_pay_count" android:layout_widt ...

  4. spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,guava限流,定时任务案例, 发邮件

    本文介绍spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,定时任务案例 集成swagger--对于做前后端分离的项目,后端只需要提供接口访问,swagger提供了接口 ...

  5. 高可用Redis(二):字符串类型

    1.Redis字符串结构 对于Redis来说,所有的key都是字符串,其value可以是string,list,hash,set,zset 比如下面的 键值对的value还可以更加复杂,比如可以是js ...

  6. 算法工程师<数学题/智力题>

    <数学题/智力题> 1.如果一个女生说,她集齐了十二个星座的前男友,我们应该如何估计她前男友的数量? https://blog.csdn.net/FnqTyr45/article/deta ...

  7. 洛谷 P2820 局域网

    题目链接 https://www.luogu.org/problemnew/show/P2820 题目背景 某个局域网内有n(n<=100)台计算机,由于搭建局域网时工作人员的疏忽,现在局域网内 ...

  8. ID3、C4.5、CART决策树介绍

    决策树是一类常见的机器学习方法,它可以实现分类和回归任务.决策树同时也是随机森林的基本组成部分,后者是现今最强大的机器学习算法之一. 1. 简单了解决策树 举个例子,我们要对”这是好瓜吗?”这样的问题 ...

  9. windows下安装Python虚拟环境virtualenvwrapper-win

      1 前言 由于Python的版本众多,还有Python2和Python3的争论,因此有些软件包或第三方库就容易出现版本不兼容的问题. 通过 virtualenv 这个工具,就可以构建一系列 虚拟的 ...

  10. podman(libpod)---github简单记录

    这个应该集成了Skopeo 和Buildah. 用于代替docker的工具包,且和cri-o共享后端代码,迟早集成进K8S~~~. (docker肿么办????) github地址: https:// ...