如果程序是单线程的,就不必担心此线程在执行时被其他线程“打扰”,就像在现实世界中,在一段时间内如果只能完成一件事情,不用担心做这件事情被其他事情打扰。但是,如果程序中同时使用多线程,好比现实中的“两个人同时通过一扇门”,这时就需要控制,否则容易引起阻塞。

为了处理这种共享资源竞争,可以使用同步机制所谓同步机制,指的是两个线程同时作用在一个对象上,应该保持对象数据的统一性和整体性。Java 提供 synchronized 关键字,为防止资源冲突提供了内置支持。共享资源一般是文件、输入/输出端口或打印机。

在一个类中,用 synchronized 关键字声明的方法为同步方法。格式如下:

class类名
{public synchronized 类型名称 方法名称(){//代码}
}

Java 有一个专门负责管理线程对象中同步方法访问的工具——同步模型监视器,它的原理是为每个具有同步代码的对象准备唯一的一把“锁”。当多个线程访问对象时,只有取得锁的线程才能进入同步方法,其他访问共享对象的线程停留在对象中等待。

synchronized 不仅可以用到同步方法,也可以用到同步块。对于同步块,synchronized 获取的是参数中的对象锁。格式如下:

synchronized(obj)
{//代码
}

当线程执行到这里的同步块时,它必须获取 obj 这个对象的锁才能执行同步块,否则线程只能等待获得锁。必须注意的是,Obj 对象的作用范围不同,控制情况也不尽相同。如下代码为简单的一种使用:

public void method()
{Object obj=new Object();synchronized(obj){//代码}
}

上述代码创建局部对象 Obj,由于每一个线程执行到 Object obj=new Object() 时都会产生一个 obj 对象,每一个线程都可以获得新创建的 obj 对象的锁而不会相互影响,因此这段程序不会起到同步作用。如果同步的是类的属性,情况就不同了。

例 1
在前面几节中,使用了 synchronized 关键字同步方法来解决非线程安全的问题。下面通过一个案例演示 println() 方法与 i-- 联合使用时“有可能”出现的另外一种异常情况,并说明其中的原因。

(1) 首先创建线程类 MyThread,该类的代码很简单,如下所示:

public class MyThread extends Thread
{private int i=5;@Overridepublic void run(){System.out.println("当前线程名称="+Thread.currentThread().getName()+",i="+(i--));//注意:代码i--由前面项目中单独一行运行改成在当前项目中在println()方法中直接进行打印}
}

(2) 编写主线程代码,首先创建一个 MyThread 线程类,再启动 5 个相同的线程。具体代码如下:

public class Test
{public static void main(String[] args){MyThread run=new MyThread(); Thread t1=new Thread(run); Thread t2=new Thread(run); Thread t3=new Thread(run); Thread t4=new Thread(run); Thread t5=new Thread(run); t1.start(); t2.start(); t3.start(); t4.start(); t5.start();}
}

从如下所示的运行效果可以看出,i 的值并不是从 5 递减 1。这是因为虽然 println() 方法在内部是同步的,但 i-- 操作却是在进入 println() 之前发生的,所以有发生非线程安全问题的概率。

当前线程名称=Thread-2,i=5
当前线程名称=Thread-3,i=2
当前线程名称=Thread-4,i=3
当前线程名称=Thread-1,i=4
当前线程名称=Thread-5,i=1

(3) 为了防止发生非线程安全问题,应继续使用同步方法。在这里使用同步块完成,修改后的代码如下:

public class MyThread extends Thread
{private int i=5;@Overridepublic void run(){synchronized (this){System.out.println("当前线程名称="+Thread.currentThread().getName()+",i="+(i--));//注意:代码i--由前面项目中单独一行运行改成在当前项目中在println()方法中直接进行打印}}
}

(4) 再次运行将看到如下所示的正常的运行效果。

当前线程名称=Thread-1,i=5
当前线程名称=Thread-2,i=4
当前线程名称=Thread-3,i=3
当前线程名称=Thread-4,i=2
当前线程名称=Thread-5,i=1

Java多线程的同步机制:synchronized相关推荐

  1. Java多线程的同步机制(synchronized)

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...

  2. java实验多线程机制_使用Java多线程的同步机制编写应用程序 PDF 下载

    使用Java多线程的同步机制编写应用程序 PDF 下载 本站整理下载: 相关截图: 主要内容: 一. 实验名称 使用Java多线程的同步机制编写应用程序 二. 实验目的及要求 1.理解并行/并发的概念 ...

  3. java多线程(二)——锁机制synchronized(同步方法)

    synchronized Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中 ...

  4. Java 多线程(六) synchronized关键字详解

    多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题. 同步机制可以使用synchronized关键字实现. 当synchroniz ...

  5. 多线程的实现与多线程的同步机制-让你轻松掌握多线程编程

    多线程的实现与多线程的同步机制 1. 多线程的实现 1.1 继承Thread类 创建一个类,这个类需要继承Thread类 重写Thread类的run方法(run方法中是业务代码) 实例化此线程类 调用 ...

  6. 线程同步机制synchronized中锁的判断以及锁的作用范围

    当我们使用多个线程访问同一资源(可以是同一个变量.同一个文件.同一条记录等)的时候,若多个线程只有读操作,那么不会发生线程安全问题,但是如果多个线程中对资源有读和写的操作,就容易出现线程安全问题. 要 ...

  7. Java线程同步机制synchronized关键字的理解

    由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问. 需要明确的几个问题: ...

  8. java 多线程跑数据_java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁...

    多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 packagethread_test;public class ThreadDemo1 extendsTh ...

  9. Java高级-线程同步机制实现

    2019独角兽企业重金招聘Python工程师标准>>> 前言 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Threa ...

最新文章

  1. 基于cnn的短文本分类_自然语言理解之(二)短文本多分类TextCNN实践
  2. 第三章GIT使用入门
  3. C++ sizeof与strlen
  4. mysql错误消息1_MySQL出错信息: Subquery returns more than 1 row及其解决方法
  5. EasyMock 使用方法与原理剖析--转载
  6. html中alert的用法_【渗透实战】通过HTML命名空间混淆绕过DOMPurify实现XSS
  7. 【Ubuntu】 Ubuntu18.04修改主机名
  8. Windows下安装苹果iPhone开发环境xcode图文教程
  9. 通俗易懂,C#如何安全、高效地玩转任何种类的内存之Span
  10. 主动断开socket链接_TCP连接与断开详解(socket通信)
  11. Android异常总结---1.异常原因: java.lang.IllegalArgumentException: URI: content://com.android.contacts/con
  12. java 连接数据库查询_JAVA连接数据库,查询功能怎么写
  13. matlab2014调用vs2015进行混合编译生成mex文件
  14. 不会优化数据库,早晚被优化!
  15. Java方法重载注意事项
  16. vmware workstation 12 密钥
  17. 数字通信学习笔记——自相关函数、随机信号
  18. 小米便签产品级的源码
  19. strip符号和节移除工具,符号表删除
  20. python-expected an indented block问题解决

热门文章

  1. Py:python利用easygui实现最简单GUI带你学习区块链技术的发展和由来
  2. 脚本:获取CSDN文章的访问量
  3. 一文弄懂神经网络中的反向传播法
  4. swift学习笔记-UI篇之UIImageView
  5. bzoj1452: [JSOI2009]Count
  6. JVM 学习笔记 1. JVM 运行模型
  7. HLG2081分苹果
  8. Coding 初级教程(二)——上传已有项目
  9. Ajax缓存解决办法
  10. 在IAR下如何查看工程的堆栈(STM32)