Java线程同步问题

本文详细解析了Java中synchronized关键字的使用方式,包括同步方法与同步代码块的区别,并通过实例展示了不同情况下线程间的同步行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        使用synchronized同步方法和同步代码块,当是两个线程调用同一对象里面的synchronized方法或者代码块时,或者另外不是synchronized方法的时候,会是什么情况呢?

public class Orange {
	private int numOne=10;
	private int numtwo=10;	
	public synchronized  void test1()   {
		
		while(numOne>0) {
			System.out.println("我是方法test1的numOne:"+numOne--);
			try {
				Thread.sleep(1000);				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		
	}
	public synchronized  void test2()   {
			
			while(numtwo>0) {
				System.out.println("我是方法test2的numtwo:"+numtwo--);				
				
			}
			
		}


}

public class Run1 implements Runnable{
	private Orange orange;
	public Run1(Orange orange) {
		this.orange=orange;
	}
	@Override
	public void run() {
		orange.test1();
		
	}
}
public class Run2 implements Runnable{
	private Orange orange;
	public Run2(Orange orange) {
		this.orange=orange;
	}
	@Override
	public void run() {
		orange.test2();
		
	}
}
public static void main(String[] args){

        Orange orange = new Orange();
	new Thread(new Run1(orange)).start();
	new Thread(new Run2(orange)).start();

}

输出:
我是方法test1的numOne:10
我是方法test1的numOne:9
我是方法test1的numOne:8
我是方法test1的numOne:7
我是方法test1的numOne:6
我是方法test1的numOne:5
我是方法test1的numOne:4
我是方法test1的numOne:3
我是方法test1的numOne:2
我是方法test1的numOne:1
我是方法test2的numtwo:10
我是方法test2的numtwo:9
我是方法test2的numtwo:8
我是方法test2的numtwo:7
我是方法test2的numtwo:6
我是方法test2的numtwo:5
我是方法test2的numtwo:4
我是方法test2的numtwo:3
我是方法test2的numtwo:2
我是方法test2的numtwo:1
        由上分析,在test1方法中sleep了1000毫秒,但是另外一个线程仍旧不去执行test2方法,两个线程共用一个Orange对象,因此可以知道,当有不同线程调用同一对象的synchronized同步方法时,另外一个线程调用同一对象的其他synchronized同步方法时,会进入阻塞状态,既第一个线程首先获得了对象锁,因而另外一个线程无法取得该对象锁,从而进入阻塞状态。

        如果同步代码块会怎么样呢?把Orange类的test2方法改成同步代码块,其他代码不变。

public class Orange {
	private int numOne=10;
	private int numtwo=10;
	Fruit fruit=new Fruit();
	
	public synchronized  void test1()   {
		
		while(numOne>0) {
			System.out.println("我是方法test1的numOne:"+numOne--);
			try {
				Thread.sleep(1000);				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		
	}
	
	public void test2() {
		synchronized (this) {
			while (numtwo>0) {
				System.out.println("我是方法test2的numtwo:"+numtwo--);
				
			}
		}
	}
	

}
输出:

我是方法test1的numOne:10
我是方法test1的numOne:9
我是方法test1的numOne:8
我是方法test1的numOne:7
我是方法test1的numOne:6
我是方法test1的numOne:5
我是方法test1的numOne:4
我是方法test1的numOne:3
我是方法test1的numOne:2
我是方法test1的numOne:1
我是方法test2的numtwo:10
我是方法test2的numtwo:9
我是方法test2的numtwo:8
我是方法test2的numtwo:7
我是方法test2的numtwo:6
我是方法test2的numtwo:5
我是方法test2的numtwo:4
我是方法test2的numtwo:3
我是方法test2的numtwo:2
我是方法test2的numtwo:1
        通过观察输出,发现跟上面的输出是一样的,从而知道synchronized(this)也是获得同一对象锁的,this指向当前对象,因而是同一个对象,如果把synchronized(this)里面的this改成其他对象呢?又会怎么样?

package com.qrj.bean;

public class Orange {
	private int numOne=10;
	private int numtwo=10;
	String strObj=new String();
	
	public synchronized  void test1()   {
		
		while(numOne>0) {
			System.out.println("我是方法test1的numOne:"+numOne--);
			try {
				Thread.sleep(1000);				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		
	}
	
	public void test2() {
		synchronized (strObj) {
			while (numtwo>0) {
				System.out.println("我是方法test2的numtwo:"+numtwo--);
				
			}
		}
	}
	

}
输出:

我是方法test1的numOne:10
我是方法test2的numtwo:10
我是方法test2的numtwo:9
我是方法test2的numtwo:8
我是方法test2的numtwo:7
我是方法test2的numtwo:6
我是方法test2的numtwo:5
我是方法test2的numtwo:4
我是方法test2的numtwo:3
我是方法test2的numtwo:2
我是方法test2的numtwo:1
我是方法test1的numOne:9
我是方法test1的numOne:8
我是方法test1的numOne:7
我是方法test1的numOne:6
我是方法test1的numOne:5
我是方法test1的numOne:4
我是方法test1的numOne:3
我是方法test1的numOne:2
我是方法test1的numOne:1
        通过观察输出,第一个线程首先执行了一次test1方法循环,然后sleep(1000),但仍旧持有该对象锁,但是从输出发现,这时候第二个线程执行了test2方法,而test2的同步代码块是synchronized(strObj),不再是this了,因而没有阻塞,就可以干点别的事情了。

        那另外的线程可不可以执行同一对象的其他没有同步的方法而不进入不阻塞状态呢?把test2方法的同步代码块改一下,其他代码不变。

public void test2() {
		
			while (numtwo>0) {
				System.out.println("我是方法test2的numtwo:"+numtwo--);
				
			}
		}

输出:

我是方法test1的numOne:10
我是方法test2的numtwo:10
我是方法test2的numtwo:9
我是方法test2的numtwo:8
我是方法test2的numtwo:7
我是方法test2的numtwo:6
我是方法test2的numtwo:5
我是方法test2的numtwo:4
我是方法test2的numtwo:3
我是方法test2的numtwo:2
我是方法test2的numtwo:1
我是方法test1的numOne:9
我是方法test1的numOne:8
我是方法test1的numOne:7
我是方法test1的numOne:6
我是方法test1的numOne:5
我是方法test1的numOne:4
我是方法test1的numOne:3
我是方法test1的numOne:2
我是方法test1的numOne:1

        通过输出知道,另外的线程可以执行同一对象的没有同步(synchronized)的方法而不进入阻塞状态,不用等待第一个线程执行的同步方法结束后才执行。


如有不正之处,还望多多指正~

标题基于SpringBoot+Vue的社区便民服务平台研究AI更换标题第1章引言介绍社区便民服务平台的研究背景、意义,以及基于SpringBoot+Vue技术的研究现状和创新点。1.1研究背景与意义分析社区便民服务的重要性,以及SpringBoot+Vue技术在平台建设中的优势。1.2国内外研究现状概述国内外在社区便民服务平台方面的发展现状。1.3研究方法与创新点阐述本文采用的研究方法和在SpringBoot+Vue技术应用上的创新之处。第2章相关理论介绍SpringBoot和Vue的相关理论基础,以及它们在社区便民服务平台中的应用。2.1SpringBoot技术概述解释SpringBoot的基本概念、特点及其在便民服务平台中的应用价值。2.2Vue技术概述阐述Vue的核心思想、技术特性及其在前端界面开发中的优势。2.3SpringBoot与Vue的整合应用探讨SpringBoot与Vue如何有效整合,以提升社区便民服务平台的性能。第3章平台需求分析与设计分析社区便民服务平台的需求,并基于SpringBoot+Vue技术进行平台设计。3.1需求分析明确平台需满足的功能需求和性能需求。3.2架构设计设计平台的整体架构,包括前后端分离、模块化设计等思想。3.3数据库设计根据平台需求设计合理的数据库结构,包括数据表、字段等。第4章平台实现与关键技术详细阐述基于SpringBoot+Vue的社区便民服务平台的实现过程及关键技术。4.1后端服务实现使用SpringBoot实现后端服务,包括用户管理、服务管理等核心功能。4.2前端界面实现采用Vue技术实现前端界面,提供友好的用户交互体验。4.3前后端交互技术探讨前后端数据交互的方式,如RESTful API、WebSocket等。第5章平台测试与优化对实现的社区便民服务平台进行全面测试,并针对问题进行优化。5.1测试环境与工具介绍测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值