java的多线程互斥主要通过synchronized关键字实现。一个线程就是一个执行线索,多个线程可理解为多个执行线索。进程有独立的内存空间,而进程中的线程则是共享数据对象资源。这样当多个执行线索在CPU的切换下交替执行,就会出现一些恶心的情况,执行的结果也是匪夷所思。第一个线程未执行完,CPU切换到另一个线程执行,由于数据资源共享,将导致程序的执行混乱。解决线程间的互斥主要就是通过synchronized来实现。

下面利用传智播客里面的代码举例分析:

package com.cqfczc.util;
/**
* 多线程的互斥技术
* @author zhenliang
*
*/
public class ThreadSynchronized {
public static void main(String[] args) {
new ThreadSynchronized().testThread();
}
private void testThread(){
final OutPutPrinter printer = new OutPutPrinter();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
printer.printer("风铃三世爱着猴子");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
printer.printer("猴子始终喜欢杨婵");
}
}
}).start();
}
     //多线程不适用互斥技术时的有问题代码
class OutPutPrinter{
public void printer(String name){
if(name == null){
throw new NullPointerException("参数不能为空!");
}
int nameLength = name.length();
for(int i=0;i<nameLength;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
          
}
}

1、自定义的对象作为锁对象 
实现方式 :synchronized(<自定义锁对象>){…} 
适用情况:当出现需要在多个类(或者多个类的实例)之间进行互斥控制时,需要采用本方法。

class OutPutPrinter{
private String lock = "大泼猴";
public void printer(String name){
if(name == null){
throw new NullPointerException("参数不能为空!");
}
int nameLength = name.length();
synchronized(lock){
for(int i=0;i<nameLength;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
} }

2、以this作为锁对象 
实现方式:synchronized(this){…},synchronized实例方法;
适用情况:适用于使用类的同一个实例(对象)作为锁对象。

        // 同步方法,相当于synchronized(this){}
public synchronized void output2(String name) {
int len = name.length();
for(int i=0; i<len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}

3、以Outputer.class作为锁对象 
Outputer类的字节码对象由jvm自动加载。 
实现方式:synchronized(Outputer.class){…} ,static synchronized方法 
适用情况:适用于整个类的所有对象都需要互斥访问的情况

        // 静态同步方法,相当于synchronized(Outputer.class){}
public static synchronized void output3(String name) {
int len = name.length();
for(int i=0; i<len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}

总结:同一个类中代码块或者方法的互斥,使用this或者类的字节码作为对象锁;当需要在多个类(或者多个类的实例)之间进行互斥控制时,使用自定义对象锁或类字节码对象锁;因为类的字节码全世界只有一份,自定义的对象锁是类内部的一个成员变量,每次创建新对象的时候属性是一样的。

线程系列2--Java线程的互斥技术的更多相关文章

  1. 【java线程系列】java线程系列之java线程池详解

    一线程池的概念及为何需要线程池: 我们知道当我们自己创建一个线程时如果该线程执行完任务后就进入死亡状态,这样如果我们需要在次使用一个线程时得重新创建一个线程,但是线程的创建是要付出一定的代价的,如果在 ...

  2. 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型

    关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...

  3. Java并发编程系列-(7) Java线程安全

    7. 线程安全 7.1 线程安全的定义 如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的. 类的线程安全表现为: 操作的原子性 内存的可见性 不 ...

  4. Java并发编程系列-(6) Java线程池

    6. 线程池 6.1 基本概念 在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理.如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数 ...

  5. 线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁

    当涉及到多线程共享数据,需要数据同步的时候,就可以考虑使用线程锁了.本篇体验线程锁的各种用法以及线程死锁.主要包括: ※ 使用lock处理数据同步※ 使用Monitor.Enter和Monitor.E ...

  6. 【阿里面试系列】Java线程的应用及挑战

    文章简介 上一篇文章[「阿里面试系列」搞懂并发编程,轻松应对80%的面试场景]我们了解了进程和线程的发展历史.线程的生命周期.线程的优势和使用场景,这一篇,我们从Java层面更进一步了解线程的使用.关 ...

  7. java线程系列之三(线程协作)

    本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7433673,转载请注明. 上一篇讲述了线程的互斥(同步),但是在很多情况 ...

  8. 【线程】linux之多线程同步互斥技术

      1.同步机制      线程同步机制主要有:互斥量/信号量/条件变量/读写锁等. 2.技术示例 创建2个计数线程A和B,每次计数加1,当为偶数时,A线程计数:当为奇数时,B线程计数.    源码: ...

  9. 并发编程系列:Java线程池的使用方式,核心运行原理、以及注意事项

    并发编程系列: 高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 线程池的缘由 java中为了提高并发度,可以使用多线程共同执行,但是如果有大量线程短时间之内被创建和销毁,会占用大量的 ...

  10. 面试官系统精讲Java源码及大厂真题系列之Java线程安全的解决办法

    1. 背景 1.1 static修饰类变量.方法.方法块.  public + static = 该变量任何类都可以直接访问,而且无需初始化类,直接使用 类名.static 变量 1.2 多个线程同时 ...

随机推荐

  1. Java学习 面向对象(下)——Java疯狂讲义th4

    面向对象(下) [TOC] 包装类 通过包装类可以把8个基本类型的值包装成对象使用. 自动拆箱.自动装箱 把字符串类型值转换成基本类型的值: 包装类的 parseXxx(String s)静态方法 包 ...

  2. centos7安装配置LVS+keepalived高可用

    Centos7-Lvs+Keepalived架构 LVS+Keepalived 介绍 1 .   LVS LVS 是一个开源的软件,可以实现 LINUX 平台下的简单负载均衡. LVS 是 Linux ...

  3. phpcms修改重置后台账号和密码

    通过Phpmyadmin等工具,打开数据库中找到v9_admin表: 把password字段值改为: 0b817b72c5e28b61b32ab813fd1ebd7f再把encrypt字段值改为: 3 ...

  4. Spring讲解-----------表达式语言

    转自:https://blog.csdn.net/u011225629/article/details/47143083 5.1  概述5.1.1  概述       Spring表达式语言全称为“S ...

  5. TCP坚持定时器

    窗口探查(window probe) 当接收方TCP缓冲区没有剩余空间后,在ACK中会通知发送方window=0,此时发送方就暂停发送数据.当接收方TCP缓冲区又有空间后,会再次发送一个ACK,告知其 ...

  6. php 生成mysql数据字典 (php5.5-5.6)

    <?php /** * 生成mysql数据字典 */ //配置数据库 $dbserver = "127.0.0.1"; $dbusername = "root&qu ...

  7. fastadmin中关联表时A为主表,想让B表和C表关联时怎么办?

    $sql = Db::connect('数据库')->table('C表')->where('status', 'normal')->field('字段 别称[不可与其他表重复]') ...

  8. 【转】container_of宏 分析

    在学习Linux驱动的过程中,遇到一个宏叫做container_of.该宏定义在include/linux/kernel.h中,首先来贴出它的代码: /** * container_of - cast ...

  9. Hive权限管理(十)

    Hive权限管理 1.hive授权模型介绍 (1)Storage Based Authorization in the Metastore Server 基于存储的授权 - 可以对Metastore中 ...

  10. Thinkphp清除缓存文件

    Thinkphp的缓存在开发中是非常烦人的,因为有的时候因为缓存的问题而出现的错误是非常难找的.删除缓存更是麻烦,还要去文件夹下删除.如果是linux开发服务器的话还要登陆服务器进行删除.所以这个时候 ...