• 同步-同步锁-死锁-线程交互-线程综合示例


    一、同步

    1.作用:为了避免多个线程同时访问并修改共享数据所导致的不安全问题。

    2.使用synchronized(对象){}方式。

    二、机制

    1.当线程要进入某个被“同步锁”锁住代码之前,线程必须先获得“同步锁对象”

    2.保证任何时刻,只有一条线程能执行被锁代码

    3.不许以“竞争资源”作为“同步对象”

    三、同步锁的释放

    1.代码完成

    2.语句块抛出异常

    3.语句块遇到break,return

    4.调用wait方法

    5.注意:sleep和yield方法不会释放同步锁

    四、对象锁池

    新建->start()->可运行<---调度任务--> 正在运行->run()完成->终止

    正在运行---阻塞事件(sleep,join)----->阻塞-----解除阻塞---->可运行

    正在运行---同步的------>阻塞对象的锁池-----获得所---->可运行

    五、代码演示

    package 同步;
    
    public class Couner implements Runnable{
        private int counter=200;
        public void run() {
            for(int i = 0;i<50;i++){
                synchronized (this) {
                    
                    counter-=2;
                    try {Thread.sleep(10);} catch (InterruptedException e) {}
                    System.out.print(counter+"   ");
                }
            }
            
            
        }
    }
    package 同步;
    
    public class TestCounersyc {
        public static void main(String[] args) {
            Couner c = new Couner();
            Thread t1 = new Thread(c);
            Thread t2 = new Thread(c);
            t1.start();
            t2.start();
        }
    }

    六、死锁

    1.定义:两个线程都在等待对方执行完毕才能往下执行时发生死锁,陷入无限等待中。

    2.解决:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。

    3.死锁代码案例

    package 死锁;
    
    public class DeadLock
    {
        private final Object left = new Object();
        private final Object right = new Object();
        
        public void leftRight() throws Exception
        {
            synchronized (left)
            {
                Thread.sleep(2000);
                synchronized (right)
                {
                    System.out.println("leftRight end!");
                }
            }
        }
        
        public void rightLeft() throws Exception
        {
            synchronized (right)
            {
                Thread.sleep(2000);
                synchronized (left)
                {
                    System.out.println("rightLeft end!");
                }
            }
        }
    }
    package 死锁;
    
    public class Thread0 extends Thread
    {
        private DeadLock dl;
        
        public Thread0(DeadLock dl)
        {
            this.dl = dl;
        }
        
        public void run()
        {
            try
            {
                dl.leftRight();
            } 
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    package 死锁;
    
    public class Thread1 extends Thread
    {
        private DeadLock dl;
        
        public Thread1(DeadLock dl)
        {
            this.dl = dl;
        }
        
        public void run()
        {
            try
            {
                dl.rightLeft();
            } 
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    package 死锁;
    
    public class Test {
        public static void main(String[] args)
        {
            DeadLock dl = new DeadLock();
            Thread0 t0 = new Thread0(dl);
            Thread1 t1 = new Thread1(dl);
            t0.start();
            t1.start();
    
            while(true);   
        }
    }


    七、线程交互

    1.wait方法使线程进入阻塞状态,直到线程得到唤醒通知,或者达到指定时间。

    注意:

    1)wait和notify方法仅能在所访问对象的同步块内调用。

    2)当线程调用wait方法进入等待状态时,会释放对象锁标记。

    2.唤醒方式

      通知唤醒-notify或notifyAll方法

      主动唤醒-到达阻塞事件

      中断唤醒-被另一个线程调用interrupt方法,收到InterruptedException异常。

    3.代码演示

    package 线程交互;
    
    public class Couner implements Runnable{
        private int counter=0;
        
        public void setCounter(int counter){
            this.counter = counter;
        }
        
        public synchronized void run() {
            if(counter<100){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            counter-=100;
            System.out.println("counter = " + counter);
            System.out.println("Counter线程结束");
        }
    }
    package 线程交互;
    
    
    public class TestCounerWait {
        public static void main(String[] args) {
            Couner c = new Couner();
            Thread t = new Thread(c);
            t.start();
            
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            
            synchronized (c) {
                c.setCounter(150);
                c.notify();
            }
            System.out.println("main线程结束");
        }
    }

    八、线程综合示例(代码)

    package 线程综合示例;
    
    public class Couner{
        private int counter=0;
        
        public synchronized int increase(int n){
            counter+=n;
            this.notify();
            System.out.printf("生产:couner=%-2d n=%-2d
    ",counter,n);
            return counter;
        }
        
        
        public synchronized int decrease(int n){
            while(counter<n){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                }
            }
            
            counter-=n;
            System.out.printf("消费:couner=%-2d n=%-2d
    ",counter,n);
            return counter;
        }
        
    }
    package 线程综合示例;
    
    public class Producer implements Runnable{
        private Couner couner;
        
        public Producer(Couner couner){
            this.couner = couner;
        }
        
        public void run() {
            for(int i=0;i<50;i++){
                couner.increase((int)(Math.random()*10));
                try {
                    Thread.sleep((int)(Math.random()*100));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                
            }
        }
            
    }
    package 线程综合示例;
    
    public class Consumer implements Runnable{
    
        private Couner couner;
        
        public Consumer(Couner couner){
            this.couner = couner;
        }
        
        public void run() {
            for(int i=0;i<50;i++){
                couner.decrease((int)(Math.random()*8));
                try {
                    Thread.sleep((int)(Math.random()*100));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                
            }
        }
            
    
    }
    package 线程综合示例;
    
    
    public class TestPC {
        public static void main(String[] args) {
            Couner couner = new Couner();
            
            
            Producer p = new Producer(couner);
            Thread t1 = new Thread(p);
            Consumer c = new Consumer(couner);
            Thread t2 = new Thread(c);
            t1.start();
            t2.start();
        }
    }
  • 相关阅读:
    界面控件DevExpress ASP.NET Controls v21.2 甘特图性能增强
    New!DevExpress ASP.NET v21.2最新版本系统环境配置要求
    界面控件DevExpress WinForm MVVM命令讲解(一)
    界面控件DevExpress WPF入门级教程 触摸滚动条
    DevExtreme初级入门教程(React篇) 应用程序模板(Part 1)
    WinForm应用界面美化攻略 MVVM 高级绑定功能
    Telerik UI组件官宣支持.NET 6 和 VS 2022,让现代UI变得更简单
    界面控件Telerik UI for WinForm初级教程 版本升级
    界面控件DevExpress WPF入门指南 表达式 & 表达式编辑器
    DevExtreme初级入门教程(React篇) 应用程序模板(Part 2)
  • 原文地址:https://www.cnblogs.com/zdf159/p/7269532.html
Copyright © 2020-2023  润新知