多线程详解2(并发)
多线程详解2(并发)
线程就是独立的执行路径;
在程序执行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;
main()称之为主线程,为系统的入口,用于执行整个线程;
在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统密切相关的,先后顺序是不能人为干预的;
对于同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;
线程会带来额外的开销,如cpu调度,并发控制开销;
每个线程在自己的工作内存交互,内存控制不当会造成数据不一致;
线程同步:处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象,这时候就需要线程同步;
线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池,形成队列,等待前面线程使用完毕,下一个线程再使用;
由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制synchronized;当一个线程获得对象的排他锁,独占资源,其他线程必须等待,使用后释放锁即可,存在以下问题:
1.一个线程持有锁会导致其他所有需要次所的线程挂起;
2.在多线程的竞争下,枷锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题;
3.如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级导致,引起性能问题;
加锁:多个线程操作同一资源的时候,给这个资源加锁,可以解决并发问题;
同步方法,在方法前加锁;
同步代码块:将要进行增删改的资源操作的代码包裹起来,就能加锁(和mysql的事务很像)
加锁等同于强制变成队列操作,必须排队;
同步块:
同步块:synchronized(Obj){}
obj称之为同步监视器;
Obj可以是任何对象,但是推荐使用共享资源作为同步监视器;
同步方法中无需指定同步监视器,因为同步方法的同步监视器就是this,就是这个对象本身,或者是class;
同步监视器的执行过程:
1.第一个线程访问,锁定同步监视器,执行其中代码;
2.第二个线程访问,发现同步监视器被锁定,无法访问;
3.第一个线程访问完毕,解锁同步监视器;
4.第二个线程访问,发现同步监视器没有锁,然后锁定,并访问;
死锁:一个对象在已经有一个带锁的资源的情况下,还要访问领一个带锁的资源;有2个以上这样的线程,就会出发死锁;多个线程互相抱着对方需要的资源,然后形成僵持,形成死锁;
Lock锁
class A{
private final ReentrantLock lock = new ReenTrantLock();
public void m(){
lock.lock();
try{
//加锁的代码
}
finally{
lock.unlock(); //释放锁;
}
}
}
生产者与消费者问题:线程之间如何通信?
管程法和信号灯法
线程池:把常用的线程放入线程池,以便重复掉用,节省时间和资源;
创建线程池,参数为:线程池大小;
ExecutorService service = Executors.newFixedThreadPool( 10);
service.execute (new MyThread( ) ); /调用执行
service,shutdown();

浙公网安备 33010602011771号