在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. BUAA-OO-电梯调度

    BUAA-OO-电梯调度 1.设计策略 需求分析 设计一个系统,使其可以根据乘客的当前楼层和目的楼层,为乘客分配电梯资源并运送其至目的楼层. 自顶向下 根据需求,可以将整个系统分成三个部分: 处理乘客 ...

  2. Ubuntu 18.04 记录

    登录后死机,关机时死机的解决方法 更新内核并安装 Nvidia 显卡驱动可解决. 在内核更新为 4.15.18,Nvidia 显卡驱动为 390 时,问题解决. 使用 LiveCD 启动,然后 mou ...

  3. 更改MySQL密码

    #安装MySQL5.7参考:https://blog.csdn.net/qq_23033339/article/details/80872136#MYSQL的基础操作参考:https://www.cn ...

  4. 我们来说说self.setinterval

    学了js的你,肯定知道setInterval方法是按照指定的周期(以毫秒计)来调用函数或计算表达,setInterval方法会不停地调用函数,直到clearInterval被调用或窗口被关闭,这个se ...

  5. VGG16 ReNetInception network

    VGG16就是运用很简单的2个filter s=2 f=2 的pool以及3x3 same padding的filter. 每pool一下以后 翻倍filter的depth Resnet就是跳级传播结 ...

  6. MySQL1:客户端/服务器架构

    一.MySQL的客户端/服务器架构 前言 之前对MySQL的认知只限于会写些SQL,本篇算是笔记,记录和整理下自己对MySQL不熟悉的地方. 大致逻辑: MySQL的服务器程序直接和我们存储的数据打交 ...

  7. [Kubernetes]关于 Kubernetes ,你想要的,都在这儿了

    陆陆续续,关于 Kubernetes 写了有 20+ 篇文章了. 今天这篇文章来一个整合,从实践到理论,可以按需查看(我是按照博客发表时间来排序的,如果后续有想要更新的内容,也会及时更新到这篇文章中) ...

  8. appniu踩坑

    1.pyCharm识别不到appnium-python-client 解决:新建项目注意选择环境,查看Project Interpreter中是否识别到了appnium-python-client 还 ...

  9. Linux apache的运行用户和用户组

    我们在安装apache后,有时在上传文件的时候,提示没有权限或者是不可写,我们都会去查文件夹的权限. 通过ls -l /var/www/html/website可以很直观的看出我们文件和文件夹的权限, ...

  10. Django --- 单表的增删改查