Java重温学习笔记,synchronized初步知识

一、问题的提出,先看下面代码的输出

public class MyDemo implements Runnable {
    private static int myCount = 0;
 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new MyDemo());
            thread.start();
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("result: " + myCount);
    }
    
    @Override // 此标签指明此方法覆盖父类同名方法。优点是编译器会帮你检查父类是否有同名方法,如没有则报错。
    public void run() {
         for (int i = 0; i < 100000; i++)   { 
             myCount++;
        }
    }
}

不管你怎样运行,它的结果不会是10*100000。这是因为在线程在运行过程中,若干线程同时修改myCount类变量,程序没有解决多线程访问共享数据的问题。synchronized就是实现每个线程依次排队操作共享数据的功能。

二、synchronized的使用场景,可以是方法,也可以是代码块

三、下面是修改后的代码

方法1. 代码块锁定。因为myCount是类变量,所以需要对类进行锁定

public class MyDemo implements Runnable {
    private static int myCount = 0;
 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new MyDemo());
            thread.start();
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("result: " + myCount);
    }
    
    @Override // 此标签指明此方法覆盖父类同名方法。优点是编译器会帮你检查父类是否有同名方法,如没有则报错。
    public void run() {
         for (int i = 0; i < 100000; i++)   { 
             synchronized (MyDemo.class) {
                 myCount++;
             }
        }
    }
}

运行结果如下:

%JAVA_HOME%\bin\java "MyDemo" ...
result: 1000000

 方法2:方法锁定。把同步代码独立出来,如下:

public class MyDemo implements Runnable {
    private static int myCount = 0;
 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new MyDemo());
            thread.start();
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("result: " + myCount);
    }
    
    // synchronized修饰静态方法
    public synchronized static void method1() {
        myCount++;
    }

    @Override // 此标签指明此方法覆盖父类同名方法。优点是编译器会帮你检查父类是否有同名方法,如没有则报错。
    public void run() {
         for (int i = 0; i < 100000; i++)   { 
             method1();
        }
    }
}

它的运行结果与上面是一样的。

本文章参考:https://www.cnblogs.com/wangwudi/p/12302668.html

posted @ 2021-06-18 14:38  那些年的事儿  阅读(96)  评论(0编辑  收藏  举报