2、传统的线程互斥synchronized
synchronized使用之基本原则:
synchronized可以锁方法,也可以锁代码片段,但要实现互斥的基本就是在想要互斥的代码上加”同一把锁“,也就是同一个对象,也就是用==判断等于true的对象
下面看一个例子:
Work.java 真正做事情的类
package com.yzl;
public class Work {
/**
* 未同步的
* @param name
*/
public void noSynwrite(String name){
for(int i=0; i<name.length(); i++){
System.out.print(name.charAt(i));
if(i == (name.length()-1)){
System.out.print("\n");
}
}
}
/**
* 使用同步块,并使用Work的实例对象做为锁
* 此方法的同步需保证是调用该方法的work对象是同一个
* @param name
*/
public void write1(String name){
synchronized (this) {
for(int i=0; i<name.length(); i++){
System.out.print(name.charAt(i));
if(i == (name.length()-1)){
System.out.print("\n");
}
}
}
}
/**
* 使用同步块,并使用Work的字节码做为锁
* @param name
*/
public void write1WithStatic(String name){
synchronized (Work.class) {
for(int i=0; i<name.length(); i++){
System.out.print(name.charAt(i));
if(i == (name.length()-1)){
System.out.print("\n");
}
}
}
}
/**
* 使用同步的方法,锁对象为ork的实例对象
* 此方法的同步需保证是调用该方法的work对象是同一个
* @param name
*/
public synchronized void write2(String name){
for(int i=0; i<name.length(); i++){
System.out.print(name.charAt(i));
if(i == (name.length()-1)){
System.out.print("\n");
}
}
}
/**
* 静态方法的同步方法,同步的对象是对象的字节码,也就是Work.class
* 如果要与上面的方法一起使用并保持互斥,则可以把write1的锁对象this改成Work.class
* @param name
*/
public synchronized static void write3(String name){
for(int i=0; i<name.length(); i++){
System.out.print(name.charAt(i));
if(i == (name.length()-1)){
System.out.print("\n");
}
}
}
}
测试类ThreadPart_2.java
package com.yzl; /**
* 传统的线程互斥
* 原理:使用同一个对象(锁)才能实现,
* 静态方法的同步则只能使用类的字节码也就是ClassName.class来做锁
* @author yzl
*
*/
public class ThreadPart_2 {
public static void main(String[] args) {
noSyn();
synWithOneObj();
synWithOneStaticObj();
} /**
* 未线程同步的
*/
private static void noSyn(){
final Work work = new Work(); Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while(true){
work.noSynwrite("wangwu");
}
}
});
thread.start(); Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
while(true){
work.noSynwrite("zhangsan");
}
}
});
thread1.start();
} /**
* 使用同一个实例对象做为锁的
*/
private static void synWithOneObj(){
final Work work = new Work(); Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while(true){
work.write1("wangwu");
}
}
});
thread.start(); Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
while(true){
work.write2("zhangsan");
}
}
});
thread1.start();
} /**
* 使用同一个类的字节码做为锁的
*/
private static void synWithOneStaticObj(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while(true){
new Work().noSynwrite("wangwu");
}
}
});
thread.start(); Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
while(true){
Work.write3("zhangsan");
}
}
});
thread1.start();
}
}
将上面ThreadPart_2的第12、13、14行代码分别依次执行,
第12行代码将出现如下类似结果:
//运行结果部分示例
zhangsan
zhwu
wangwu
wangangsan
zhangsawangwu
第13和14行将是正常的打印各自的名字
2、传统的线程互斥synchronized的更多相关文章
- 传统的线程互斥技术:Synchronized关键字
多个线程操作同一个方法或变量时常常出现错误,要保证每个线程都正常运行就要通过加锁,每次只有一个能够拿到锁通过.如下: package cn.sp.thread; /** * Created by 2Y ...
- 线程互斥synchronized
/** * * 线程互斥,采用synchronized关键字可以实现线程与线程之间的互斥,要注意的是在synchronized上的对象要是同一个,才可以 * 保证在同一时刻,只有一个线程可以执行syn ...
- 【Java并发专题之三】Java线程互斥、协作原理
(I)Java线程互斥原理之synchronized原理 从JDK5引入CAS原子操作,但没有对synchronized关键字做优化,而是增加了J.U.C.concurrent,concurrent包 ...
- 【原】iOS多线程之线程间通信和线程互斥
线程间通信 1> 线程间通信分为两种 主线程进入子线程(前面的方法都可以) 子线程回到主线程 2> 返回主线程 3> 代码 这个案例的思路是:当我触摸屏幕时,会在子线程加载图片,然后 ...
- java线程安全— synchronized和volatile
java线程安全— synchronized和volatile package threadsafe; public class TranditionalThreadSynchronized { pu ...
- java多线程与线程并发二:线程互斥
本文章内容整理自:张孝祥_Java多线程与并发库高级应用视频教程 当两条线程访问同一个资源时,可能会出现安全隐患.以打印字符串为例,先看下面的代码: // public class Test2 { p ...
- Java线程同步synchronized的理解
JVM中(留神:马上讲到的这两个存储区只在JVM内部与物理存储区无关)存在一个主内存(Main Memory),Java中所有的变量存储在主内存中,所有实例和实例的字段都在此区域,对于所有的线程是共享 ...
- GIL与线程互斥锁
GIL 是解释器级别的锁,是限制只有一个原生线程运行,防止多个原生线程之间修改底层的共享数据.而线程互斥锁是防止多个线程同时修改python内存空间的共享数据.
- C#中的多线程与线程互斥
通过多线程,C#可以并行地执行代码. 每一个线程都有它独立的执行路径,所有线程都能访问共有变量. 这就引发了线程竞争 这时就需要使用线程安全的处理方式使得线程互斥 先来看一段多线程代码 using S ...
随机推荐
- JUnit4单元测试入门教程
本文按以下顺序讲解JUnit4的使用 下载jar包 单元测试初体验 自动生成测试类 执行顺序 @Test的属性 下载jar包## 下载地址 在github上,把以下两个jar包都下载下来. 下 ...
- Caffe常用层参数介绍
版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/Cheese_pop/article/details/52024980 DATA crop:截取原图像中一个 ...
- fabric 清理环境 运行SDK
清理环境: rm -rf /tmp/* rm -rf ~/.hfc-key-store/ 启动网络: docker ps -a create channel: join channel: 清理npm ...
- AsyncHttpClient的连接池使用逻辑
AsyncHttpClient的连接池结构很简单, NettyConnectionsPool内部重要的几个变量如下 // 连接池, 通过 host 区分不同的池 private final Concu ...
- RFC 868 -- TIME Protocol
INTERNET STANDARD Errata Exist Network Working Group J. Postel - ISI Request for Comments: 868 K. Ha ...
- Guava之Iterables使用示例
这是一个常量工具类.Iterables类包含了一系列的静态方法,来操作或返回Iterable对象. public final class Iterables { private Iterables() ...
- 检查安装的 DirectX 版本
https://support.microsoft.com/zh-cn/help/179113/how-to-install-the-latest-version-of-directx DxDiag ...
- 利用wsdl2java工具生成webservice的客户端代码
1.JDK环境 2.下载apache-cxf发布包:http://cxf.apache.org/download.html 目前最新版本为3.2.6, 解压后如下: 解压发布包,设置CXF_HOME ...
- linux下获取硬盘使用情况[总结]
1.前言 在嵌入式设备中,硬盘空间非常有限,在涉及到经常写日志的进程时候,需要考虑日志的大小和删除,不然很快就硬盘写满,导致日志程序崩溃.为了捕获硬盘写满的异常场景,我们需要在写日志过程中判断硬盘空间 ...
- IDEA实现序列号接口
idea自动生成serialVersionUID (2013-12-15 08:12:09)转载▼ Setting->Plugins 找到一个叫 GenerateSerialVersionUID ...