多线程学习总结----synchronized

      之前写过一篇多线程学习总结(一),基础的都介绍过了。这次主要讲解一下多线程并发处理的关键字synchronized~

一、什么是synchronized

简单的来讲,synchronized同步锁就是用来解决共享资源竞争的问题。
实现思路:
1.先把共享的执行资源用synchronized包裹,并传递一个共享对象作为synchronized同步锁的钥匙。
2.只有获取到这个共享对象钥匙的线程,才可以获取执行synchronized包裹的内容。
3.没有获取到的线程,进入阻塞,等待锁资源释放。

二、什么实例锁和全局锁

实例锁:锁在某个实例对象上。如果该类是单例,那么该锁也是具有全局锁的概念。实例锁对应的就是synchronized关键字。
全局锁:该锁针对的是类,无论实例多少个对象,那么线程都共享该锁。全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。

synchronized使用

具体应用方式有以下三种:

    1. public void synchronized XXX(){}
    2. synchronized(this){}
    3. public static void synchronized XXX(){}

区别:

  方式1和2锁的都是当前执行体所在的对象,属于实例锁. synchronized方法是用synchronized修饰方法,这是一种粗粒度锁;

  synchronized代码块是用synchronized修饰代码块,这是一种细粒度锁。一般情况下,细颗粒度锁速度要高于粗颗粒度

  而方式3由于加了static,锁的就是当前类对象.属于全局锁(注意,java中类对象只有一个,而对象是有类对象实例化产生的,会有多个)

下面演示synchronized的使用

代码一:
    package com.my.thread;

    public class ThreadDemo implements Runnable{

        @Override
        public void run() {
            synchronized(this){
                for(int i=0;i<5;i++){
                    try {
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName()+" loop "+i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }

        public static void main(String[] args) {
            Runnable threadDemo = new ThreadDemo();
            new Thread(threadDemo,"t1").start();
            new Thread(threadDemo,"t2").start();
        }

    }
结果:
    t1 loop 0
    t1 loop 1
    t1 loop 2
    t1 loop 3
    t1 loop 4
    t2 loop 0
    t2 loop 1
    t2 loop 2
    t2 loop 3
    t2 loop 4
代码二:
    package com.my.thread;

    public class ThreadDemo implements Runnable{

        @Override
        public void run() {
            synchronized(this){
                for(int i=0;i<5;i++){
                    try {
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName()+" loop "+i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }

        public static void main(String[] args) {

            new Thread(new ThreadDemo(),"t1").start();
            new Thread(new ThreadDemo(),"t2").start();
        }

    }
结果:
    t2 loop 0
    t1 loop 0
    t2 loop 1
    t1 loop 1
    t1 loop 2
    t2 loop 2
    t2 loop 3
    t1 loop 3
    t1 loop 4
    t2 loop 4

两段代码,我们可以看出来synchronized(this) 这个锁的this是指的当前执行体所在的对象。

而代码一中,可以看到锁的this是同一个对象,所以线程一和线程二互斥执行的。而代码二中,由于锁的对象并非同一个对象,所以执行起来并无影响。

 

再看一下方式3的使用

代码:
    package com.my.thread;

    public class ThreadDemo1 {
        static class Demos {
           public static synchronized void isSyncA(){
                for(int i=0;i<5;i++){
                    try {
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName()+" say "+i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
        Demos demos1 = new Demos();
        Demos demos2 = new Demos();

        public void deal(){
            Thread t1 = new Thread(new Runnable(){
                @Override
                public void run() {
                    demos1.isSyncA();
                }
            },"t1");
            Thread t2 = new Thread(new Runnable(){
                @Override
                public void run() {
                    demos2.isSyncA();
                }
            },"t2");
            t1.start();
            t2.start();
        }

        public static void main(String[] args) {
            ThreadDemo1 threadDemo1 = new ThreadDemo1();
            threadDemo1.deal();
        }
    }

结果:
    t2 say 0
    t2 say 1
    t2 say 2
    t2 say 3
    t2 say 4
    t1 say 0
    t1 say 1
    t1 say 2
    t1 say 3
    t1 say 4

从上面可以看出来,static synchronized是锁的当前类对象,和创建的对象无关。所以最后结果也显示了出,线程之间执行公共代码产生互斥。

本次就到此为之了,多线程的学习我也才刚刚开始,希望日后多学习多总结多分享了~~~

posted @ 2019-08-06 23:02  笑里笑外~  阅读(178)  评论(0编辑  收藏  举报