zoukankan      html  css  js  c++  java
  • 同步-同步锁-死锁-线程交互-线程综合示例

    一、同步

    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();
        }
    }
  • 相关阅读:
    SVN服务器搭建(一)
    排序算法二:冒泡排序
    【LeetCode】136. Single Number
    【LeetCode】217. Contains Duplicate
    【LeetCode】189. Rotate Array
    【LeetCode】122. Best Time to Buy and Sell Stock II
    【LeetCode】26. Remove Duplicates from Sorted Array
    【LeetCode】20. Valid Parentheses
    【LeetCode】680. Valid Palindrome II
    【LeetCode】345. Reverse Vowels of a String
  • 原文地址:https://www.cnblogs.com/zdf159/p/7269532.html
Copyright © 2011-2022 走看看