synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较

Posted 安卓笔记侠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较相关的知识,希望对你有一定的参考价值。

synchronized用于多线程设计,有了synchronized关键字,多线程程序的运行结果将变得可以控制。synchronized关键字用于保护共享数据。

synchronized实现同步的机制:synchronized依靠"锁"机制进行多线程同步,"锁"有2种,一种是对象锁,一种是类锁

1.依靠对象锁锁定

初始化一个对象时,自动有一个对象锁。synchronized {普通方法}依靠对象锁工作,多线程访问synchronized方法,一旦某个进程抢得锁之后,其他的进程只有排队对待。


synchronized {普通方法}依靠对象锁工作,多线程访问synchronized方法,一旦某个进程抢得锁之后,其他的进程只有排队对待。
 
synchronized void method{}功能上,等效于
void method{
   synchronized(this) {
    ...
   }
}
通过代码看比较清楚:
public class TestSynchronized {
    public synchronized void method1() throws InterruptedException {
        System.out.println("method1 begin at:" + System.currentTimeMillis());
        Thread.sleep(6000);
        System.out.println("method1 end at:" + System.currentTimeMillis());
    }
    public synchronized void method2() throws InterruptedException {
        while(true) {
            System.out.println("method2 running");
            Thread.sleep(200);
        }
    }
    static TestSychronized instance = new TestSychronized();
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance.method1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for(int i=1; i<4; i++) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread1 still alive");
                }                    
            }
        });
        
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance.method2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread1.start();
        thread2.start();    
        
    }
}

 运行结果:thread2一直等到thread1中的method1执行完了之后才执行method2,说明method1和method2互斥

synchronized {修饰代码块}的作用不仅于此,synchronized void method{}整个函数加上synchronized块,效率并不好。在函数内部,可能我们需要同步的只是小部分共享数据,其他数据,可以自由访问,这时候我们可以用 synchronized(表达式){//语句}更加精确的控制
  • 2.synchronized {static方法}此代码块等效于
void method{
   synchronized(Obl.class)
   }
}
使用该类的类对象的锁定去做线程的共享互斥.
package com.free4lab.lol;

public class TestSychronized {
    public synchronized static void method1() throws InterruptedException {
        System.out.println("method1 begin at:" + System.currentTimeMillis());
        Thread.sleep(6000);
        System.out.println("method1 end at:" + System.currentTimeMillis());
    }
    public synchronized static void method2() throws InterruptedException {
        while(true) {
            System.out.println("method2 running");
            Thread.sleep(200);
        }
    }
    static TestSychronized instance1 = new TestSychronized();
    static TestSychronized instance2 = new TestSychronized();
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance1.method1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for(int i=1; i<4; i++) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread1 still alive");
                }                    
            }
        });
        
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance2.method2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread1.start();
        thread2.start();    
        
    }
}

输出效果也是method1和method2互斥

 
  • 3.synchronized {run方法}run方法的锁定.
这个举例比较好说
package com.free4lab.lol;

public class TestSychronized {
    static TestSychronized instance = new TestSychronized();
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
                public synchronized void run() {
                    
                    for(int i=1; i<4; i++) {
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("Thread1 still alive, " + i);
                    }                    
                }
        });
        new Thread(thread1).start();
        new Thread(thread1).start();
    }
}

如果加了synchronized当前线程取完所有数据后,才会释放锁,输出结果是有序的

Thread1 still alive, 1
Thread1 still alive, 2
Thread1 still alive, 3
Thread1 still alive, 1
Thread1 still alive, 2
Thread1 still alive, 3

  

 

以上是关于synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较的主要内容,如果未能解决你的问题,请参考以下文章

一定要会的synchronized关键字的用法

一定要会的synchronized关键字的用法

Synchronized的基本使用

synchronized关键字修饰非静态方法与静态方法的区别

总结 synchronized

JAVA并发编程:synchronized及其实现原理