多线程安全和线程同步

问题

线程不安全问题

在多个线程使用同一个资源的时候,有可能存在一个资源被一个线程占有,但一系列操做(原子操做:不可再分割的操做)并未执行完成,执行过程当中的资源被其余线程拿去用了。java

同步

在一个线程执行原子操做时,其余线程不能占有资源安全

1.同步代码块

同步锁在括号中,是线程共同享有的资源ide

@Override
public void run() {
        for (int i = 0; i < 50; i++) {
            String name = Thread.currentThread().getName();
            synchronized (this) {//同步锁,线程共同享有的资源,这里的this是指Apple对象
            if (num > 0) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(name + "吃了第" + num-- + "个苹果");
            }
        }
    }
}

2.同步方法(不能同步run方法)

使用synchronized来修饰方法,对于非静态方法,同步锁是this;对于非静态方法,同步锁是当前方法所在类的字节码对象 类名.class性能

@Override
public void run() {
    for (int i = 0; i < 50; i++) {
        test();
    }
}

private synchronized void test() {
    String name = Thread.currentThread().getName();
    if (num > 0) {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + "吃了第" + num-- + "个苹果");
    }
}

3.锁机制

synchronized采用了自动加锁和释放锁的机制,手动加锁的方法更加透明,功能更增强大ui

package java_study;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Apple3 implements Runnable {
    public int num = 50;
    //1.因为 Lock 是一个接口,使用其实现类 ReentrantLock 得到一个锁对象
    private final Lock lock = new ReentrantLock();
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            eat();
        }
    }

    private void eat() {
        //2.在方法的开始加锁吗,须要使用try-finally保证释放锁的进行
        lock.lock();
        try {
            if (num > 0) {
                Thread.sleep(10);
                String name = Thread.currentThread().getName();
                System.out.println(name + "吃了第" + num-- + "个苹果");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //3.释放锁
            lock.unlock();
        }
    }

}

public class ClockDemo {
    public static void main(String[] args) {
        Apple3 a = new Apple3();
        new Thread(a, "A").start();
        new Thread(a, "B").start();
        new Thread(a, "C").start();
    }
}

!同步的优缺点:

  • 使用synchronized提升了线程安全性,下降了性能,尽可能减少做用域 如:StringBuffer类 ArrayList HashMap
  • 不适用synchronized提高了性能。下降了线程安全性 如:StringBuilder类 Vector Hashtable

!Sleep 对锁的影响

  • Sleep 不会致使锁丢失,会一直占用资源直到从 sleep 唤醒
相关文章
相关标签/搜索