Java多线程常见问题总结

1、进程、线程、多线程原理

进程:进程就是一段程序的执行过程,代表一个“正在运行”的应用程序。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。进程有三个状态:就绪(获取除CPU的所有资源)、运行(获得了处理器分配的资源,程序开始执行)和阻塞(如等待i/o操作之后才能开始执行,等待和睡眠状态,这时即使把处理机分配给进程也无法运行

线程: 是进程的一个实体,是CPU调度和分配的基本单位,线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器、一组寄存器和栈),但是它可以与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。

引入线程的优点:

(1)易于调度

(2)提高并发性。通过线程可以方便有效的实现并发。

(3)开销小。创建线程比创建进程快,所需要的开销小。

(4)有利于发挥多处理器的功能。通过创建多线程,每个线程都在一个处理器上运行,从而实现应用程序的并行,使每个处理器都得到充分运行。
 

2、进程和线程的不同

引用:https://blog.csdn.net/xy_cpp/article/details/79397706

(1)  拥有资源和调度:进程是拥有资源的独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。线程是指进程内的一个执行单元,是调度和分配的基本单位,

(2)  通信:线程之间的通信比较方便。统一进程下的线程共享数据(比如全局变量,静态变量),通过这些数据来通信,快捷方便,但要处理好这些访问的同步与互斥。而进程之间的通信只能通过进程通信的方式进行(如管道,信号,消息队列,共享内存,信号量,套接字)。

(3)  执行:每个独立的线程有自己的一个程序入口,顺序执行序列和程序的出口,但是不能独立执行,必须依附与程序之中,由应用程序提供多个线程的并发控制。

(4)  系统开销:进程有独立的地址空间,在创建或撤消进程时,系统都要为之分配和回收资源,导致开销明显大。运行一个进程中的线程,共享大部分数据,使用相同的地址空间,因此启动一个线程,切换一个线程远比进程操作要快,花费也要小得多。

(5)  健壮性:多进程的程序要比多线程的程序健壮。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。而线程只是一个进程中的不同执行路径,有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。

3、 synchronized、ReentrantLock的区别

引用:https://blog.csdn.net/iteye_494/article/details/82654607

synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上:

(1)ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁

(2)ReentrantLock可以获取各种锁的信息

(3)ReentrantLock可以灵活地实现多路通知

另外,二者的锁机制其实也是不一样的。ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word,这点我不能确定。

4、 ReadWriteLock

由于ReentrantLock某些时候有局限。如果使用ReentrantLock,可能本身是为了防止线程A在写数据、线程B在读数据造成的数据不一致,但这样,如果线程C在读数据、线程D也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降低了程序的性能。因为这个才诞生了读写锁ReadWriteLock。ReadWriteLock是一个读写锁接口,ReentrantReadWriteLock是ReadWriteLock接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。

猜你喜欢

转载自blog.csdn.net/sinat_41144773/article/details/89016280