刚毕业的时候,总是搞不清什么是线程安全,只记得网上说,只要方法做到可重入,就是线程安全的,晕头晕脑,一头雾水。
今年读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一个,就不会存在线程安全的问题了。
虽然线程安全是一个不是很容易理解的话题,但上面两个例子却反映了两个最普遍的线程安全问题。遇到线程问题,最快的解决方法就是去掉变量共享。单线程的程序,永远不会出现线程安全问题。
相关推荐
2. **线程同步**:为了确保线程安全,多线程程序通常需要同步机制。vc提供了多种同步原语,如`CRITICAL_SECTION`用于互斥访问资源,`Event`用于线程间的通信,`Mutex`用于全局锁,以及`Semaphore`控制对共享资源的...
- **附录A**:线程安全总结,总结了Cocoa和Core Foundation框架中各组件的线程安全性。 #### 第一章 关于多线程编程 ##### 1.1 什么是多线程 多线程是指在单个进程内同时执行多个线程的能力。每个线程都是独立...
在进行Socket编程时,经常需要处理多线程的情况,以实现客户端与服务端之间的并发通信。 首先,要理解Socket编程的基本概念,Socket是计算机网络通信的基本构件,它提供了不同主机上运行的程序之间的网络通信接口。...
《Delphi 2007中的多线程技术与实战示例》 Delphi 2007是一款经典的集成开发环境,它支持丰富的编程特性,其中包括对多线程的高效处理。多线程技术在软件开发中至关重要,尤其是在处理耗时操作如网络通信、大量数据...
- **单block单thread向量加法**:虽然表面上看起来像是并行处理,但实际上仍然是串行的,因为每个线程负责整个向量的加法运算。 - **优化方案**:合理划分线程,每个线程负责计算一部分结果,通过这种方式真正实现...
- **线程安全的库**:使用线程安全的第三方库或API可以简化多线程编程。 #### 三、线程管理 1. **线程成本**: - 创建和销毁线程都有一定的开销。 - 过多的线程可能导致上下文切换频繁,反而降低性能。 2. **...
线程共享同一进程的内存空间,因此它们之间的通信更为高效。本文将深入探讨Linux环境下多线程的设计、创建、管理和相关属性。 1. **线程创建** 使用`pthread_create`函数可以创建一个新的线程。这个函数需要四个...
- 规定了程序中的各种变量(线程共享变量)的访问规则。 - 描述了主内存与线程工作内存之间的交互协议。 - **主要特性**: - 原子性、可见性和有序性。 - 保证了线程间数据的一致性。 #### 十四、线程池的种类 ...
WaitHandle(如EventWaitHandle、AutoResetEvent、ManualResetEvent)和条件变量(ConditionVariable)是线程间通信的重要工具,它们可以用于线程间的信号传递,实现线程的唤醒和等待。 九、线程局部存储 ...
线程安全与同步问题** 在多线程环境中,多个线程可能同时访问共享资源,可能导致数据不一致或竞态条件。`threading`模块提供的同步原语如锁、条件变量、信号量等,可以帮助解决这些问题,确保数据的一致性。 **5....
7. **线程安全的函数**:在多线程编程中,一些标准库函数可能不是线程安全的,例如全局变量的使用。因此,开发过程中需要注意使用线程安全的函数或库,如C++11引入的`std::mutex`、`std::lock_guard`等工具。 8. **...
5. **线程同步与线程安全** - 在多线程环境中,共享数据的访问可能导致数据不一致。使用`lock`关键字、`Mutex`或`Semaphore`可以确保同一时间只有一个线程访问共享资源。 6. **后台线程** - 通过设置`...
Java多线程设计模式是Java开发中不可或缺的一部分,它涉及到如何高效、安全地在多个执行线程之间共享资源和协调任务。在这个主题中,我们将深入探讨一些关键的概念、设计模式和最佳实践,以帮助开发者更好地理解和...
在这个例子中,因为我们只是简单地打印数值,没有共享变量,所以不存在竞态条件。但如果涉及共享资源,如全局变量,就需要使用同步机制,如`synchronized`关键字或`java.util.concurrent`包中的工具,来防止数据不...
示例代码中没有对线程进行命名,但可以使用`Thread.currentThread().setName("自定义名称")`为线程设置有意义的名字,方便在日志或调试时识别线程。 8. **输出控制**: 示例中使用`System.out.println()`输出线程...
- **使用Thread类**:通过实例化`System.Threading.Thread`类并调用`Start()`方法来创建和启动新线程。 ```csharp Thread thread = new Thread(new ThreadStart(YourMethod)); thread.Start(); ``` - **使用Task类**...