java锁与同步基础入门Word格式文档下载.docx
《java锁与同步基础入门Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《java锁与同步基础入门Word格式文档下载.docx(16页珍藏版)》请在冰豆网上搜索。
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+"
正在出售第"
+(tickets--)+"
张票"
);
}
}finally{
//释放锁
lock.unlock();
}
}
}
}
SellTicketDemo.java
/*
*虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,
*为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock。
*
*Lock:
*voidlock():
获取锁。
*voidunlock():
释放锁。
*ReentrantLock是Lock的实现类.
*/
publicclassSellTicketDemo{
publicstaticvoidmain(String[]args){
//创建资源对象
SellTicketst=newSellTicket();
//创建三个窗口
Threadt1=newThread(st,"
窗口1"
Threadt2=newThread(st,"
窗口2"
Threadt3=newThread(st,"
窗口3"
//启动线程
t1.start();
t2.start();
t3.start();
2同步的弊端
DieLock.java
packagecn.itcast_02;
publicclassDieLockextendsThread{
privatebooleanflag;
publicDieLock(booleanflag){
this.flag=flag;
if(flag){
synchronized(MyLock.objA){
System.out.println("
ifobjA"
synchronized(MyLock.objB){
System.out.println("
ifobjB"
}else{
synchronized(MyLock.objB){
elseobjB"
synchronized(MyLock.objA){
elseobjA"
DieLockDome.java
*同步的弊端:
*A:
效率低
*B:
容易产生死锁
*死锁:
*两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象。
*举例:
*中国人,美国人吃饭案例。
*正常情况:
*中国人:
筷子两支
*美国人:
刀和叉
*现在:
*中国人:
筷子1支,刀一把
*美国人:
筷子1支,叉一把
publicclassDieLockDemo{
DieLockdl1=newDieLock(true);
DieLockdl2=newDieLock(false);
dl1.start();
dl2.start();
MyLock.java
publicclassMyLock{
//创建两把锁对象
publicstaticfinalObjectobjA=newObject();
publicstaticfinalObjectobjB=newObject();
3资源类
GetThread.java
packagecn.itcast_03;
publicclassGetThreadimplementsRunnable{
privateStudents;
publicGetThread(Students){
this.s=s;
//Students=newStudent();
System.out.println(s.name+"
---"
+s.age);
SetThread.java
publicclassSetThreadimplementsRunnable{
publicSetThread(Students){
s.name="
林青霞"
;
s.age=27;
Student,java
publicclassStudent{
Stringname;
intage;
StudentDemo.java
*分析:
*资源类:
Student
*设置学生数据:
SetThread(生产者)
*获取学生数据:
GetThread(消费者)
*测试类:
StudentDemo
*问题1:
按照思路写代码,发现数据每次都是:
null---0
*原因:
我们在每个线程中都创建了新的资源,而我们要求的时候设置和获取线程的资源应该是同一个
*如何实现呢?
*在外界把这个数据创建出来,通过构造方法传递给其他的类。
publicclassStudentDemo{
//创建资源
Students=newStudent();
//设置和获取的类
SetThreadst=newSetThread(s);
GetThreadgt=newGetThread(s);
//线程类
Threadt1=newThread(st);
Threadt2=newThread(gt);
//启动线程
4序列流
packagecn.itcast_04;
synchronized(s){
System.out.println(s.name+"
privateintx=0;
if(x%2==0){
s.name="
//刚走到这里,就被别人抢到了执行权
s.age=27;
}else{
刘意"
//刚走到这里,就被别人抢到了执行权
s.age=30;
x++;
Student.java
*问题2:
为了数据的效果好一些,我加入了循环和判断,给出不同的值,这个时候产生了新的问题
同一个数据出现多次
姓名和年龄不匹配
*CPU的一点点时间片的执行权,就足够你执行很多次。
*线程运行的随机性
*线程安全问题:
是否是多线程环境是
是否有共享数据是
*C:
是否有多条语句操作共享数据是
*解决方案:
*加锁。
*注意:
*A:
不同种类的线程都要加锁。
*B:
不同种类的线程加的锁必须是同一把。
5线程运行
packagecn.itcast_05;
*问题3:
虽然数据安全了,但是呢,一次一大片不好看,我就想依次的一次一个输出。
*通过Java提供的等待唤醒机制解决。
*等待唤醒:
*Object类中提供了三个方法:
*wait():
等待
*notify():
唤醒单个线程
*notifyAll():
唤醒所有线程
*为什么这些方法不定义在Thread类中呢?
*这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象。
*所以,这些方法必须定义在Object类中。
//判断有没有
if(s.flag){
s.wait();
//t1等着,释放锁
//x=1
//修改标记
s.flag=true;
//唤醒线程
s.notify();
//唤醒t2,唤醒并不表示你立马可以执行,必须还得抢CPU的执行权。
//t1有,或者t2有
booleanflag;
//默认情况是没有数据,如果是true,说明有数据
6