多线程线程安全开发

多线程、高并发、线程安全
    synchronized同步方法
        摘要:
        1、方法内部的私有变量不存在线程安全问题;
        2、多线程中用不同的对象调用同一个对象锁同步方法(非静态),是异步执行的;
        3、 类锁跟对象锁是两把锁,一线程A类型a对象调用对象锁同步方法M1,二线程A类调用类锁同步(静态同步)方法M2,
            结果:M1跟M2的执行顺序是异步的,因为 这是两把锁(不会出现锁占用),执行方法M1时用的是对象锁,
            执行方法M2时(不管是用 其他对象去调用还是 直接用类名调用)用的是类锁,所以执行顺序是异步的。
            如果都调用M2,不管是几个不同对象(或者用类名)那么就都 用的类锁,这样的话将是同步执行的;
        4、synchronized修饰的 非静态方法、synchronized修饰 (this){代码块} 针对的都是对象锁,一个对象一把锁,不同对象不同锁,
            如:一线程A类型a1对象调用对象锁同步方法M1,二线程A类型对象a2(跟a1不是一个实体)也调用对象锁同步方法M1,
            结果:两个M1的执行顺序是异步的,因为两个对象两个对象锁;
        5、synchronized修饰的 静态方法、synchronized修饰 (A.class){代码块} 针对的都是类锁,类锁只有一把,全局共享一把类锁,
            多线程中不管是用任何对象调用这个类锁方法,还是用类名直接调用,多线程中这个方法执行的顺序都是同步的;
        6、对象锁同步方法M1,对象锁同步方法M2,一线程中用A类型对象a调用M1,二线程中也用A类型对象a(同一个实例),调用
            方法M2,结果: 两个方法执行的顺序是同步的,因为是锁占有(同一个对象同一个锁);
        7、类锁同步方法M1,类锁同步方法M2,一线程中(用不管任何A类型对象、类名)调用M1,二线程中调用方法M2,
            结果:两个方法执行的顺序是同步的,因为锁占有(占用着同一把类锁);
        8、类锁同步方法M1,对象锁同步方法M2,一线程中调用M1(不管是对象调用还是类调用),二线程中调用M2(不管是不是同一个实例对象),
            结果:M2、M1都是异步执行,两个线程中掉用的是 不同的锁方法,不会出现锁占用(第3点已经说明);
package base.thread;
public class A {
    public static synchronized void M2() {
        for(int i=0;i<100;i++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("M2:"+i);
        }
    }
    
    public synchronized void M1() {
        for(int i=0;i<100;i++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("M1:"+i);
        }
    }
    
}
package base.thread;
public class TwoKindsOfLockMain {
    public static void main(String[] args) {
        A a = new A();
        new Thread(() -> {
            a.M1();
        }).start();
        new Thread(() -> {
            A.M2();
        }) .start();
        
    }
}
M1:0
M2:0
M1:1
M2:1
M1:2
M2:2
...
    内存可见性  volatile修饰词
package base.thread;
/**
 * @author G_Y
 * 2018年3月12日
 * 说明:内存可见性经典测试
 * 线程工作区如果不跟主内存进行交互 则 数据不能进行 同步
 * 调用静态、native方法也能跟主内存交互
 */
public class MainThreadTest {
    private static boolean b = Boolean.FALSE;//volatile 修饰就能及时知道数据的值
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            int i = 0;
            while (!b) {
                i++;
                /*try {
                    Thread.sleep(100);//调用native方法也能跟主内存交互
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }*/
                //System.out.println(1);//调用同步方法也能跟主内存交互  当前线程内存跟主内存同步
            }
            System.out.println("thread over");
        }).start();
        Thread.sleep(1000);
        b = Boolean.TRUE;
        System.out.println("main over");
    }
}
    线程死锁
        用类锁举例:
        如:线程1中占用着类型A的类锁等待着类型B的类锁释放,线程2中占用着类型B的类锁等待着类型A的类锁释放,
        然后其他线程都 没机会使用类A的 所以类锁 方法,也 不能使用类B的所以 类锁 方法
        也可用对象锁举例:



你可能感兴趣的:(java基础)