多线程(8)线程同步机制
一:解决自己以前的疑问
比如:创建三个对象
class Test7 implements Runnable{
private int i=10;
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+i--);
}
public static void main(String[] args) {
Test7 test7=new Test7();
Test7 test71=new Test7();
Test7 test72=new Test7();
Thread thread=new Thread(test7,"zph");
Thread thread1=new Thread(test71,"wlw");
Thread thread2=new Thread(test72,"nyy");
thread.start();
thread1.start();
thread2.start();
}
}
Thread-nyy10
Thread-zph10
Thread-wlw10
这里面的thread与thread1与thread2都是互不相干的。 (这是三个人操作三个对象)
创建一个对象:
class Test7 implements Runnable{
private int i=10;
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+i--);
}
public static void main(String[] args) {
Test7 test7=new Test7();
Thread thread=new Thread(test7,“zph”);
Thread thread1=new Thread(test7,“wlw”);
Thread thread2=new Thread(test7,“nyy”);
thread.start();
thread1.start();
thread2.start();
}
}这个时候三个人操作一个对象,是相互影响额
Thread-wlw10
Thread-zph9
Thread-nyy8
二:并发
①并发:同一个对象被多个线程同时操作(我们上面写的一个对象)
三:线程同步
①线程同步:处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象,这时候我们就需要线程同步,线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下个线程再使用。
②形成条件:队列+锁
③由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机子synchronized,当一个线程获得对象的排他锁,独占资源,其他线程必须等待,使用后释放锁即可,
存在问题:
A:一个线程持有锁会导致其他所有需要此锁的线程挂起。
B:在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题。
C:如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能问题。
1.不安全卖票
class Mai{
public static void main(String[] args) {
MaiPiao maiPiao=new MaiPiao();
Thread thread1=new Thread(maiPiao,"zph");
Thread thread2=new Thread(maiPiao,"wlw");
Thread thread3=new Thread(maiPiao,"nyy");
thread1.start();
thread2.start();
thread3.start();
}
}
class MaiPiao implements Runnable{
private int Num=20;
boolean flag=true;
@Override
public void run() {
while (flag) {
if (Num<=1){
flag=false;
}
buy();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void buy(){
System.out.println(Thread.currentThread().getName()+"买的第"+Num--+"张");
}
}
wlw买的第20张
zph买的第19张
nyy买的第18张
nyy买的第17张
wlw买的第16张
zph买的第15张
zph买的第14张
nyy买的第13张
wlw买的第12张
zph买的第11张
nyy买的第10张
wlw买的第9张
zph买的第8张
nyy买的第7张
wlw买的第6张
zph买的第5张
nyy买的第4张
wlw买的第4张
zph买的第3张
nyy买的第2张
wlw买的第1张
四:同步方法和同步代码块
1.同步方法:锁的是this,是这个类的对象
①同步方法,public synchronized void method(int args【】)
②synchronized方法控制对象的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行
③缺陷:若将一个大的方法声明为synchronized将会影响效率。
class Mai{
public static void main(String[] args) {
MaiPiao maiPiao=new MaiPiao();
Thread thread1=new Thread(maiPiao,"zph");
Thread thread2=new Thread(maiPiao,"wlw");
Thread thread3=new Thread(maiPiao,"nyy");
thread1.start();
thread2.start();
thread3.start();
}
}
class MaiPiao implements Runnable{
private int Num=20;
boolean flag=true;
@Override
public void run() {
while (flag) {
if (Num<=1){
flag=false;
}
buy();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void buy(){
System.out.println(Thread.currentThread().getName()+"买的第"+Num--+"张");
}
}
zph买的第20张
nyy买的第19张
wlw买的第18张
zph买的第17张
nyy买的第16张
wlw买的第15张
nyy买的第14张
zph买的第13张
wlw买的第12张
zph买的第11张
nyy买的第10张
wlw买的第9张
zph买的第8张
nyy买的第7张
wlw买的第6张
zph买的第5张
nyy买的第4张
wlw买的第3张
zph买的第2张
nyy买的第1张
2.同步代码块 可以锁任何对象,不仅仅是this(锁的对象就是变化的量,需要增删改的对象)
①方法里面需要修改的内容才需要锁,锁的太多,浪费资源。
②同步快:synchronized(obj){}
③obj称之为同步监视器,obj可以是任何对象,但是推荐使用共享资源作为同步监视器
同步方法中无法指定同步监视器,因为同步方法的同步监视器就是this,就是这个对象本身,或者是class
④同步监视器的执行过程:
A;第一个线程访问,锁定同步监视器,执行其中代码
B:第二个线程访问,发现同步监视器被锁定,无法访问
C:第一个线程访问完毕,解锁同步监视器
D:第二个线程访问,发现同步监视器没有说,然后锁定并访问
浙公网安备 33010602011771号