zoukankan      html  css  js  c++  java
  • 线程同步(线程安全处理Synchronized)与死锁

    一  线程同步

    java中提供了线程同步机制,它能够解决上述的线程安全问题。

             线程同步的方式有两种:

    方式1:同步代码块

      方式2:同步方法

    1 同步代码块

    同步代码块: 在代码块声明上 加上synchronized

    synchronized (锁对象) {
        可能会产生线程安全问题的代码
    }

    同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。

    使用同步代码块,对电影院卖票案例中Ticket类进行如下代码修改

    package com.oracle.demo01;
    
    public class Myticket implements Runnable {
        private int ticket=100;
        private Object obj=new Object();
        public void run() {
            while(true){
                synchronized (obj) {
                if(ticket>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"出售第"+ticket--+"张票");
                }
                }
            }
        }
        
    }

    运行结果为:

    这样就解决了线程安全的问题

    2  同步方法

      同步方法:在方法声明上加上synchronized

    public synchronized void method(){
           可能会产生线程安全问题的代码
    }

    同步方法中的锁对象是 this

    使用同步方法,对电影院卖票案例中Ticket类进行如下代码修改:

    package com.oracle.demo01;
    
    public class Myticket2 implements Runnable {
        private int ticket=100;
        //同步方法是否有锁对象?有   this
        //静态同步方法有锁对象?有,MyTicket2.class
        //同步怎么保证安全性?没有锁的线程不能执行只能等
        //加了同步,线程进同步判断锁的时候,比如,获取锁,释放锁,导致运行速度慢
        //StringBuilder比StringBuffer快的原因
        //StringBuffer里面的所有方法都加了同步关键字,所以慢,但安全
        //StringBuilder是没有的,所以快,但不安全
        public synchronized void sale(){
            //可能会产生线程安全问题的代码
            if(ticket>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"出售第"+ticket--+"张票");
            }
        }
        public void run() {
            while(true){
                sale();
            }
        }
        
    }

    二  死锁

    同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉。

    package com.oracle.demo02;
    
    public class DeadLock implements Runnable {
        private int i=0;
        public void run() {
            while(true){
                if(i%2==0){
                    //先进A同步,再进B同步
                    synchronized (LockA.locka) {
                        System.out.println("if...locka");
                        synchronized (LockB.lockb) {
                            System.out.println("if...lockb");
                        }
                    }
                }else{
                    //先进B同步,再进A同步
                    synchronized (LockB.lockb) {
                        System.out.println("else...lockb");
                        synchronized (LockA.locka) {
                            System.out.println("else...locka");
                        }
                    }
                }
                i++;
            }
        }
    }

    程序无线等待

  • 相关阅读:
    使用Redis的理由
    从输入网址到显示网页的全过程分析
    Node.js初识
    GET和POST的数据传递到底有何区别?
    第四五六周学习进度
    首尾相接整数数组中最大子数组的和
    网页版四则运算
    团队介绍及项目简介
    整数数组中最大子数组的和
    软件工程个人作业03
  • 原文地址:https://www.cnblogs.com/zzq123/p/10248621.html
Copyright © 2011-2022 走看看