操作系统中线程和进程的概念:
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。
比如在Windows系统中,一个运行的exe就是一个进程。
动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的
并发性:任何进程都可以同其他进程一起并发执行
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
异步性:每个进程都以相互独、不可预知的速度向前推进
结构特征:进程由程序、数据和进程控制块三部分组成。
线程是指进程中的一个执行流程,一个进程中可以运行多个线程。
比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
线程的五种状态:
新生状态(New):当一个线程的实例被创建即使用new关键字和Thread类或其子类创建一个线程对象后,
此时该线程处于新生状态。 此时线程不是活着的(not alive);
就绪状态(Runnable):通过调用线程实例的start()方法来启动线程使线程进入就绪状态;
但还没有被分配到CPU,处于线程就绪队列;此时线程是活着的(alive);
运行状态(Running):一旦获取CPU,线程就进入运行状态,线程的run()方法才开始被执行;
如果在给定的时间内没有执行结束,就会被系统给换下来回到线程的就绪状态;
此时线程是活着的(alive);
阻塞状态(Blocked):通过调用join()、sleep()、wait()或者资源被暂用使线程处于阻塞状态;
此时线程是活着的(alive)
死亡状态(Dead):当一个线程的run()方法运行完毕或被中断或被异常退出,该线程到达死亡状态。
处于Dead状态调用start()方法,会出现异常
注:部分文档上会出现四种状态的说法,实际上是把“就绪状态”+“运行状态”=可执行状态
关于对象锁:
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在java里边就是拿到某个同步对象的锁(一个对象只有一把锁);
如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池等待队列中)。
取到锁后,他就开始执行同步代码(被synchronized修饰的代码);线程执行完同步代码后马上就把锁还给同步对象,
其他在锁池中等待的某个线程就可以拿到锁执行了同步代码。这样就保证了同步代码在统一时刻只有一个线程在执行。
即:一个线程拿到了什么样的对象锁,就能打开什么样的synchronized,而同一对象锁只能在一个线程的手中
死锁:当两个线程相互等待对方释放“锁”时就会发生死锁。
如何避免死锁
1 使用事务时,尽量缩短事务的逻辑处理过程,及早提交或回滚事务;
2 设置死锁超时参数为合理范围,如:3分钟-10分种;超过时间,自动放弃本次操作,避免进程悬挂;
3 优化程序,检查并避免死锁现象出现;
4 .对所有的脚本和SP都要仔细测试,在正式版本之前。
5 所有的SP都要有错误处理(通过@error)
6 一般不要修改SQL SERVER事务的默认级别。不推荐强行加锁
可重入锁的概念是 自己可以再次获得自己的内部锁
重进入的实现是通过每个锁关联一个请求计数和一个占有它的线程,当计数为0时,认为锁是未被占有的,线程请时求一个未被占有的锁,
jvm将记录锁的占有者,并将请求计数置为一,如果同一个线程再次请求,计数器将递增,每次占用线程退出同步块计数器值将递减,
直到计数器为0,锁释放,如果内部锁不是可重入的,代码将死锁
来源:https://www.cnblogs.com/zhujunxiao/p/5104128.html