Java中锁的基础(1)-----synchronized

      很多刚开始学习Java的同学们,对于锁的概念是有些模糊不清的,再加上没有系统的总结和归纳,到后面碰到了越来越多的锁,变得更加混乱了,接下来看看我对于锁的梳理,希望对大家有所帮助。

为什么需要锁?锁的作用是什么?

因为在多线程环境下,对一个共享数据有多个语句操作这个共享数据,会引发安全问题,所以就需要加锁来保证不引发安全问题

刚入Java这个语言,第一次碰到锁,基本上就是从多线程开始遇见第一个锁----synchronized

什么是synchronized?  作用是什么?基本使用方法是什么?

synchronized翻译过来就是同步的意思,所以synchronized也称为同步锁,就是被修饰的代码块和方法只能有一个线程执行,达到并发安全的效果。

 synchronized 的使用方法有两种:

1.同步代码块格式使用

synchronized(任意对象) { 
	多条语句操作共享数据的代码 
}

synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁

同步的好处:解决了多线程的线程安全问题。

同步的坏处:当线程很多的时候,每个线程都会去判断同步代码块上面的锁,这样子是很浪费资源的。

结合代码理解:

public class SellTicket implements Runnable {
    private int tickets = 100;
    private Object obj = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (obj) { // 对可能有安全问题的代码加锁,多个线程必须使用同一把锁
                //t1进来后,就会把这段代码给锁起来
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                        //t1休息100毫秒
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //窗口1正在出售第100张票
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                    tickets--; //tickets = 99;
                }
            }
            //t1出来了,这段代码的锁就被释放了
        }
    }
}

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st = new SellTicket();

        Thread t1 = new Thread(st, "窗口1");
        Thread t2 = new Thread(st, "窗口2");
        Thread t3 = new Thread(st, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

2.同步方法的格式:

同步方法:就是把synchronized关键字加到方法上

修饰符 synchronized 返回值类型 方法名(方法参数) { 
	方法体;
}

同步方法的锁对象是什么呢? this

2.2静态同步方法

修饰符 static synchronized 返回值类型 方法名(方法参数) { 
	方法体;
}

同步静态方法的锁对象是什么呢? 类名.class

public class MyRunnable implements Runnable {
    private static int ticketCount = 100;

    @Override
    public void run() {
        while(true){
            if("窗口一".equals(Thread.currentThread().getName())){
                //同步方法
                boolean result = synchronizedMthod();
                if(result){
                    break;
                }
            }

            if("窗口二".equals(Thread.currentThread().getName())){
                //同步代码块
                synchronized (MyRunnable.class){
                    if(ticketCount == 0){
                       break;
                    }else{
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        ticketCount--;
                        System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
                    }
                }
            }

        }
    }

    private static synchronized boolean synchronizedMthod() {
        if(ticketCount == 0){
            return true;
        }else{
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticketCount--;
            System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
            return false;
        }
    }
}

public class Demo {

 public static void main(String[] args) {
      MyRunnable mr = new MyRunnable();

      Thread t1 = new Thread(mr);
      Thread t2 = new Thread(mr);

      t1.setName("窗口一");
      t2.setName("窗口二");

      t1.start();
      t2.start();
  }
     在 Java 6 之后 Java 官方对从 JVM 层面对 synchronized 较大优化,所以现在的 synchronized 锁效率也优化得很不错了。
    JDK1.6 对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。

你可能感兴趣的:(java,职场和发展)