`
donlianli
  • 浏览: 340934 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
Group-logo
Elasticsearch...
浏览量:218840
社区版块
存档分类
最新评论

识别线程安全-共享变量与单实例

阅读更多

刚毕业的时候,总是搞不清什么是线程安全,只记得网上说,只要方法做到可重入,就是线程安全的,晕头晕脑,一头雾水。

今年读Java并发编程,对并发有了进一步的了解,结合我们项目的实际应用,谈一下我对线程安全的认识。

一、共享变量(share varibles)引起线程安全

如果没有共享,就不会有线程安全问题。比如,你写的就是一个简单的helloword程序,不会有线程安全问题。但如果你的程序是一个web项目,并且里面有一个全局适用的缓存对象,那么就会涉及到线程安全问题。

下面是一个静态方法,根据code_id,得到code_name的方法。

public class CodeHelper {
	private static Map<Integer,String> CODE_DATA ;
	public static void initCode(){
		//load from db ..
	}
	public static String getCodeNameById(int codeId){
		if(CODE_DATA==null){
			initCode();
		}
		return CODE_DATA.get(codeId);
	}
}

 变量CODE_DATA就会涉及到线程安全问题。我们考虑,如果同时有两个线程调用getCodeNameById的方法,那么initCode方法就会被执行两边,而这却不是我们希望看到的。所以说,只要涉及到静态变量,我们就要小心了,静态变量,有可能存在线程安全问题。

 

二,单实例引起线程安全

我们知道,spring中的bean默认都是单实例(prototype=singleton)的,也就是说,spring里面的bean,其所有的成员变量都基本上是与静态变量是类似的。bean的任何方法,都必须代是可重入的,而不能在某个方法里面,设置bean的某个值,并且依赖其状态。比如,下面的代码就会出现线程问题。

public class JavaBean {
	private String myname;
	public void aservice(String paraName,int otherPara){
		//在spring的默认配置下在这里设值,另一个方法使用是错误的
		this.myname=paraName;
		bservice();
	}
	private void bservice() {
		String goodName= this.myname;
		//other work
	}
	public String getMyname() {
		return myname;
	}
	public void setMyname(String myname) {
		this.myname = myname;
	}
}

如果有两个线程A和B,同时进入aservice,A线程设置myname="AName",然后在执行到bservice线程阻塞,此时B线程进入,将myname="BName",然后进入bservice得出正确结果而退出。B线程执行后,myname="BName",A线程恢复,在bservice的方法执行时,使用的myname="BName",计算肯定会出错。但如果你每次使用JavaBean的时候,都是new一个,就不会存在线程安全的问题了。

 

 

虽然线程安全是一个不是很容易理解的话题,但上面两个例子却反映了两个最普遍的线程安全问题。遇到线程问题,最快的解决方法就是去掉变量共享。单线程的程序,永远不会出现线程安全问题。

 

 

 

 

 

0
0
分享到:
评论

相关推荐

    vc多线程编程实例

    2. **线程同步**:为了确保线程安全,多线程程序通常需要同步机制。vc提供了多种同步原语,如`CRITICAL_SECTION`用于互斥访问资源,`Event`用于线程间的通信,`Mutex`用于全局锁,以及`Semaphore`控制对共享资源的...

    linux多线程实例

    - **资源共享**:同一进程内的线程共享许多资源,如全局变量、进程代码、大多数数据结构、信号处理程序、信号设置、打开的文件、当前工作目录以及用户ID和组ID。 - **独立属性**:每个线程也有自己独有的属性,包括...

    多线程编程指南

    - **附录A**:线程安全总结,总结了Cocoa和Core Foundation框架中各组件的线程安全性。 #### 第一章 关于多线程编程 ##### 1.1 什么是多线程 多线程是指在单个进程内同时执行多个线程的能力。每个线程都是独立...

    C#Socket多线程编程实例.pdf

    在进行Socket编程时,经常需要处理多线程的情况,以实现客户端与服务端之间的并发通信。 首先,要理解Socket编程的基本概念,Socket是计算机网络通信的基本构件,它提供了不同主机上运行的程序之间的网络通信接口。...

    Delphi2007多线程示范,可选1-10个线程

    《Delphi 2007中的多线程技术与实战示例》 Delphi 2007是一款经典的集成开发环境,它支持丰富的编程特性,其中包括对多线程的高效处理。多线程技术在软件开发中至关重要,尤其是在处理耗时操作如网络通信、大量数据...

    GPU-4CUDA编程实例

    - **单block单thread向量加法**:虽然表面上看起来像是并行处理,但实际上仍然是串行的,因为每个线程负责整个向量的加法运算。 - **优化方案**:合理划分线程,每个线程负责计算一部分结果,通过这种方式真正实现...

    ios 多线程编程指南.pdf

    - **线程安全的库**:使用线程安全的第三方库或API可以简化多线程编程。 #### 三、线程管理 1. **线程成本**: - 创建和销毁线程都有一定的开销。 - 过多的线程可能导致上下文切换频繁,反而降低性能。 2. **...

    linux多线程设计及示例

    线程共享同一进程的内存空间,因此它们之间的通信更为高效。本文将深入探讨Linux环境下多线程的设计、创建、管理和相关属性。 1. **线程创建** 使用`pthread_create`函数可以创建一个新的线程。这个函数需要四个...

    java面试题2024资源下载

    - 规定了程序中的各种变量(线程共享变量)的访问规则。 - 描述了主内存与线程工作内存之间的交互协议。 - **主要特性**: - 原子性、可见性和有序性。 - 保证了线程间数据的一致性。 #### 十四、线程池的种类 ...

    C#多线程编程实战Code源代码

    WaitHandle(如EventWaitHandle、AutoResetEvent、ManualResetEvent)和条件变量(ConditionVariable)是线程间通信的重要工具,它们可以用于线程间的信号传递,实现线程的唤醒和等待。 九、线程局部存储 ...

    win32多线程程序设计侯捷译.rar

    7. **线程安全的函数**:在多线程编程中,一些标准库函数可能不是线程安全的,例如全局变量的使用。因此,开发过程中需要注意使用线程安全的函数或库,如C++11引入的`std::mutex`、`std::lock_guard`等工具。 8. **...

    在C#中实现创建多线程.rar

    5. **线程同步与线程安全** - 在多线程环境中,共享数据的访问可能导致数据不一致。使用`lock`关键字、`Mutex`或`Semaphore`可以确保同一时间只有一个线程访问共享资源。 6. **后台线程** - 通过设置`...

    Python内置库:threading(多线程操作).docx

    线程安全与同步问题** 在多线程环境中,多个线程可能同时访问共享资源,可能导致数据不一致或竞态条件。`threading`模块提供的同步原语如锁、条件变量、信号量等,可以帮助解决这些问题,确保数据的一致性。 **5....

    java多线程设计模式

    Java多线程设计模式是Java开发中不可或缺的一部分,它涉及到如何高效、安全地在多个执行线程之间共享资源和协调任务。在这个主题中,我们将深入探讨一些关键的概念、设计模式和最佳实践,以帮助开发者更好地理解和...

    java的thread类重写run方法的双线程从1加到100

    在这个例子中,因为我们只是简单地打印数值,没有共享变量,所以不存在竞态条件。但如果涉及共享资源,如全局变量,就需要使用同步机制,如`synchronized`关键字或`java.util.concurrent`包中的工具,来防止数据不...

    java 多线程例子.doc

    示例代码中没有对线程进行命名,但可以使用`Thread.currentThread().setName("自定义名称")`为线程设置有意义的名字,方便在日志或调试时识别线程。 8. **输出控制**: 示例中使用`System.out.println()`输出线程...

    C#多线程学习.pdf

    - **使用Thread类**:通过实例化`System.Threading.Thread`类并调用`Start()`方法来创建和启动新线程。 ```csharp Thread thread = new Thread(new ThreadStart(YourMethod)); thread.Start(); ``` - **使用Task类**...

Global site tag (gtag.js) - Google Analytics