非线程安全问题

news/2024/5/17 16:17:27 标签: 线程安全, synchronized

线程安全主要是指多个线程对同一个对象中的同一个实例变量进行操作时会出现值被更改、值不同步的情况,进而影响程序的执行流程。

比如两个账号同时登陆的情况:

例子说明:

一个非线程安全环境:

package com.zxc.thread.test;

public class LoginTest {
	private static String usernameRef;
	private static String passwordRef;
	public static void doPost(String username,String password){
		usernameRef = username;
		try {
			if(username.equals("a")){
				Thread.sleep(5000);
			}
			passwordRef = password;
			System.out.println("username=" + usernameRef + " password=" + passwordRef);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}		
	}
}
线程ALogin.java代码如下:
package com.zxc.thread.test;

public class ALogin extends Thread{
	@Override
	public void run(){
		LoginTest.doPost("a", "aa");
	}
}
线程BLogin.java代码如下:

package com.zxc.thread.test;


public class BLogin extends Thread {
	@Override
	public void run(){
		LoginTest.doPost("b", "bb");
	}
}
运行类Run.java代码如下:
package com.zxc.thread.test;

public class Run {
	public static void main(String[] args) {
		ALogin a = new ALogin();
		a.start();
		BLogin b = new BLogin();
		b.start();
	}
}
运行结果:
username=b password=bb
username=b password=aa
这个就是非线程安全的体现,要解决这个问题,可以使用synchronizsd关键字,synchronized可以在任意对象及方法上加锁,而加锁的这段代码成为“互斥区”或“临界区”,当一个线程想要执行同步方法里面的代码时,线程首先尝试去拿这把锁,如果能够拿到这把锁,那么这个线程就可以执行synchronized里面的代码,如果拿不到,这个线程就会不断地尝试拿这把锁,直到能够拿到为止,而且是有多个线程同时去争抢这把锁。

修改LoginTest.java代码:

public class LoginTest {
	private static String usernameRef;
	private static String passwordRef;
	synchronized public static void doPost(String username,String password){
		usernameRef = username;
		try {
			if(username.equals("a")){
				Thread.sleep(5000);
			}
			passwordRef = password;
			System.out.println("username=" + usernameRef + " password=" + passwordRef);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}		
	}
}
运行结果:
username=a password=aa
username=b password=bb




http://www.niftyadmin.cn/n/1735703.html

相关文章

synchronized与volatile的区别

1)关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法以及代码块,随着JDK新版本的发布,synchronized关键字在执行效率…

toLowerCase方法

toLowerCase()方法用来返回一个字符串,该字符串中的字母被转换成小写字母,而且对非字母字符不会产生影响 示例如下: public class TwoLowerCaseTest {public static void main(String[] args) {String t "Hello World AQWEsd123^&…

java中计算包含汉字字符串的长度

java中: 1字符2字节,1字节8位 英文和数字占一个字节,中文占一个字符,也就是两个字节 在计算的字符串长度的时候,若有汉字,直接用String.length()方法是没法计算出准确的长度,如: …

sql插入语句返回自增主键

在操作数据库中,插入一条记录,表中的主键是自增的,如果我们需要获得这个主键,就需要在插入的时候,返回这条主键,写法如下:INSERT INTO gusers_xxxx_log(user_id,admin_user,change_amount,total…

定时任务用到的cron时间表达式 CronTrigger

CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表。 CronTrigger,你可以指定触发的时间表如“每星期五中午”,或“每个工作日9:30时”&a…

java中获取当前时间以及对当前时间操作详解

java中时间的操作一直是自己的一个短板,希望这次总结后,会加深印象 在jdk1.0中,Date类是唯一的一个代表时间的类,但是Date类不便实现国际化,所以从JDK1.1开始,推荐使用Calendar类进行时间和日期的处理 一…

快速入门uniapp——从环境搭建到项目实践

🙂博主:小猫娃来啦 🙂文章核心:快速入门uniapp——从环境搭建到项目实践 文章目录 初步介绍UniApp开发环境搭建下载和安装UniApp开发工具创建新项目(HBuilderX)开发工具界面介绍 UniApp基础知识页面结构页面…

sql 时间转换问题 from_unixtime() UNIX_TIMESTAMP()

from_unixtime()是MySQL里的时间函数 date为需要处理的参数(该参数是Unix 时间戳),可以是字段名,也可以直接是Unix 时间戳字符串 后面的 %Y%m%d 主要是将返回值格式化 例如: mysql>SELECT FROM_UNIXTIME( 1249488000, %Y%m%d ) ->20071120 mysql>SELECT…