`

Java多线程——synchronized的问题

阅读更多

一直以来都存在这样的问题:

多线程操作同一对象。该对象有一个方法为m1,另一个方法为m2,那么当有一条线程执行m1时,同时该线程获得该对象的锁。那么另一个线程能否调用m2呢?

 

试验代码1:

public class ThreadSafeObject {
	public int i=0;
	public synchronized void add(){
		System.out.println(Thread.currentThread().getName()+";开始调用safeObject的add()方法,调用之前的值为:"+i);
		System.out.println("add方法执行5s");
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		i++;
		System.out.println(Thread.currentThread().getName()+";开始调用safeObject的sub()方法,调用之后的值为:"+i);
	}
	
	public synchronized void sub(){
		System.out.println(Thread.currentThread().getName()+";开始调用safeObject的sub()方法,调用之前的值为:"+i);
		System.out.println("sub方法执行1s");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		i--;
		System.out.println(Thread.currentThread().getName()+";开始调用safeObject的sub()方法,调用之后的值为:"+i);
		
	}
	
}

 

public class TestThreadAdd  implements Runnable{
	ThreadSafeObject safeObject ;
	
	public TestThreadAdd(ThreadSafeObject safeObject){
		 this.safeObject = safeObject;
	}
	
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+",开始执行。");
		safeObject.add();
		System.out.println(Thread.currentThread().getName()+",结束执行。");
		
	}
	
}

 

public class TestThreadSub  implements Runnable{
	ThreadSafeObject safeObject ;
	
	public TestThreadSub(ThreadSafeObject safeObject){
		 this.safeObject = safeObject;
	}
	
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+",开始执行。");
		safeObject.sub();
		System.out.println(Thread.currentThread().getName()+",结束执行。");
	}
	
}

 

public class Main {
	public static void main(String[] args) throws InterruptedException {
		ThreadSafeObject threadSafeObject = new ThreadSafeObject();
		
		new Thread(new TestThreadAdd(threadSafeObject)).start();
		Thread.sleep(200);
		new Thread(new TestThreadSub(threadSafeObject)).start();
		
	}
}

该代码段的执行结果如下:

Thread-0,开始执行。
Thread-0;开始调用safeObject的add()方法,调用之前的值为:0
add方法执行5s
Thread-1,开始执行。
Thread-0;开始调用safeObject的sub()方法,调用之后的值为:1
Thread-1;开始调用safeObject的sub()方法,调用之前的值为:1
sub方法执行1s
Thread-0,结束执行。
Thread-1;开始调用safeObject的sub()方法,调用之后的值为:0
Thread-1,结束执行。

 

可以看到当Thread-0执行了5s的add()方法后,Thread-1才能执行sub()方法。

可见,当Thread-0没有执行完add()方法之前,Thread-1是被阻塞的,且是没有获取线程锁的方式阻塞。

 

 

 

试验代码2:

把ThreadSafeObject的sub()方法的synchronized去掉。

public class ThreadSafeObject {
	......
	
	public /*synchronized*/ void sub(){
                ......
		
	}
	
}

 执行结果如下:

Thread-0,开始执行。
Thread-0;开始调用safeObject的add()方法,调用之前的值为:0
add方法执行5s
Thread-1,开始执行。
Thread-1;开始调用safeObject的sub()方法,调用之前的值为:0
sub方法执行1s
Thread-1;开始调用safeObject的sub()方法,调用之后的值为:-1
Thread-1,结束执行。
Thread-0;开始调用safeObject的sub()方法,调用之后的值为:0
Thread-0,结束执行。

 

可以看到:Thread-1没有等Thread-0的执行结束。即Thread-1不需要去获取共有对象的锁。

 

 

试验结论

synchronized关键字是强制线程获取对象的锁标志。如果没有该关键字,则线程不去等待锁的获取,而直接操作对象。

 

分享到:
评论

相关推荐

    Java多线程——线程八锁案例分析.docx

    被synchronized修饰的方法,锁的对象是方法的调用者。因为两个方法的调用者是同一个,所以两个方法用的是同一个锁,先调用方法的先执行。

    【后端】 java基础(5.8)java高级基础之线程——synchronized关键字

    java基础(5.8)java高级基础之线程——synchronized关键字 本章主要讲线程,至于带上进程的原因是为了方便大家对进程和线程有个概念(咳,主要原因是鄙人也不太会进程~)。 首先简单说下我个人对进程和线程的理解。...

    java多线程设计模式详解(PDF及源码)

    去睡觉吧 第11章 Thread-Specific Storage——每个线程的保管箱 第12章 Active Object——接受异步消息的主动对象 总结 多线程程序设计的模式语言 附录A 练习问题的解答 附录B Java的内存模型 附录C Java线程的...

    Java多线程之synchronized&volatile基础篇

    一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel ...

    Java多线程基础——Lock类

    Lock类是Java类来提供的功能,丰富的api使得Lock类的同步功能比synchronized的同步更强大。本文对此进行详细介绍,下面跟着小编一起来看下吧

    Java并发学习笔记(二)——Synchronized关键字与ReetrantLock同步锁

    被Synchronized 关键字描述的方法或代码块在多线程环境下同一时间只能由一个线程进行访问,因为在持有当前锁的线程执行完成之前,其他线程想要调用相关方法就必须进行排队,直到当前线程执行完成才释放锁给其他线程...

    Java多线程编程 线程同步机制.docx

    线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题。锁正是基于这种思路实现的一种...

    如何在Java中正确使用 wait, notify 和 notifyAll

    举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    对Java语言的每个语法都提供了一个或多个例程讲解 大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 ...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    对Java语言的每个语法都提供了一个或多个例程讲解 大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 ...

    并发编程面试专题.pdf

    1) 现在有 T1、T2、T3 三个线程,你怎样保证 T2 在 T1 执行完后执行,T3 在 T2 执行完后执行? 2) 在 Java 中 Lock 接口比 synchronized 块的优势是...15) 你在多线程环境中遇到的常见的问题是什么?你是怎么解决它的?

    Java典型模块

    第1篇 Java开发必备基础 第1章 搭建Java开发环境 1.1 Java的过去、现在和未来 1.1.1 Java的历史 ...第31章 俄罗斯方块游戏网络版(Swing+多线程+网络编程) 31.1 俄罗斯方块游戏项目原理 31.1.1 基本原理 ...

    Java SE实践教程 pdf格式电子书 下载(四) 更新

    第3章 当一个变成多个——集合框架的基本概念 53 .3.1 讲解 54 3.1.1 集合概述 54 3.1.2 Collection接口 54 3.1.3 泛型(Generics) 56 3.1.4 Map接口 57 3.2 练习 59 3.2.1 创建课程管理系统 59 3.3 小结 ...

    Java SE实践教程 源代码 下载

    第3章 当一个变成多个——集合框架的基本概念 53 .3.1 讲解 54 3.1.1 集合概述 54 3.1.2 Collection接口 54 3.1.3 泛型(Generics) 56 3.1.4 Map接口 57 3.2 练习 59 3.2.1 创建课程管理系统 59 3.3 小结 ...

    Lock锁的底层原理完整版

    Lock锁,一种线程同步机制,其主要功能是防止多个线程同时访问同一代码块,从而避免因并发问题引发的数据不一致或其他错误。...总的来说,Lock锁是Java多线程编程中的重要工具,能够有效保障程序运行的正确性和稳定性。

    Java SE实践教程 pdf格式电子书 下载(一) 更新

    第3章 当一个变成多个——集合框架的基本概念 53 .3.1 讲解 54 3.1.1 集合概述 54 3.1.2 Collection接口 54 3.1.3 泛型(Generics) 56 3.1.4 Map接口 57 3.2 练习 59 3.2.1 创建课程管理系统 59 3.3 小结 ...

    这就是标题—— JUC.pdf

    多线程锁 并发下的集合类 List Set Map Callable接口 线程创建的方式 callable / runnable FutureTask JUC常用辅助类 CountDownLatch (减少计数器) CyclicBarrier(加法计数器) Semaphore(信号量,流量控制) ...

    java经典面试2010集锦100题(不看你后悔)

    —————————————————————————————————————— 题目1: 下面不属于基本类型的是:c (选择1项) A) boolean B) long C) String D) byte 题目2:d 如下程序中: (1)public class ...

Global site tag (gtag.js) - Google Analytics