目录
◎多线程的概念
优点:
提高cpu利用率
提高程序的响应
改善程序结构,将复杂任务分为多个线程,独立运行
缺点:
线程越多占用内存就更多
需要协调和管理
(通过提升硬件配置可解决)
*多个线程之间对共享资源的访问会相互影响(龟兔赛跑,买票)
◎线程同步
●并发:在一个时间段内一次执行操作(抢票),看似同时进行,其实是一个一个执行
●并行:多个cpu同时执行多个任务
●线程同步(‘同步’就是排队+锁)
几个线程之间要排队,一个个对共享资源进行操作,而不是同时进行
为了保证数据在方法中被访问时的正确性,在访问时加入锁机制
●模拟买票
○解决办法:
1.使用synchronized(同步锁)关键字进行修饰
(1)synchronized修饰代码块
synchronized (锁对象){
同步代码块
}
锁对象:必须多个线程访问/对应同一个对象
【使用该对象(用static修饰,必须内存中只有一个)的对象头的一块空间(如果被用了就为1,线程出去就恢复为0)来记录锁的状态】
使用该对象来记录有没有线程进入到同步代码块中
(2)synchronized修饰方法
锁不需要我们提供了,会默认提供锁对象
synchronized如果修饰的是非静态的方法,锁的对象是this
synchronized如果修饰的是静态方法,锁的对象就是类的class对象,一个类只有一个class对象
(出现异常自动释放锁,自动加自动释放)
2.Reentrantlock
JDK中提供一个加锁的对象reentrantlock//要加static修饰
Reentrantlock.lock();//加锁
Reentrantlock.unlock();//释放锁
(手动加,手动释放,把释放锁放在finally中【如果不放,出现异常后不会执行释放锁,程序就一直在while中循环,无法结束】,保证释放锁)
Reentrantlock只能对某段代码块加锁,不能对整个方法加锁
Reentrantlock和synchronized区别:
相同点:都实现了加锁的功能
不同点:
synchronized是一个关键字,Reentrantlock是一个类
synchronized修饰代码块和方法,Reentrantlock只能修饰代码块
synchronized可以隐式的加锁和释放锁,运行过程中出现异常自动释放锁
Reentrantlock需要手动的添加锁和释放锁,建议在finally代码块中释放锁
◎线程通信
相互牵制,相互控制的问题
wait();//等待
notify();//唤醒等待中的线程,(调用了wait方法的线程),如果有多个线程根据优先等级进行唤醒
notifyAll();//唤醒所有的线程
这三个方法都是object类中定义的方法
这三个方法必须在同步代码块中使用
这三个方法必须通过为锁的对象调用
sleep和wait的区别:
sleep时间到了线程自动进行,不需要唤醒
wait需要其他线程唤醒才能继续进行