精华内容
下载资源
问答
  • Synchronized关键字可以用来修饰4种不同类型的代码块: 实例方法静态方法实例方法中的代码块静态方法中的代码块同步方法 public synchronized void add(int value){this.count += value;}注意到此处Synchronized...

    Synchronized关键字可以用来修饰4种不同类型的代码块: 实例方法

    静态方法

    实例方法中的代码块

    静态方法中的代码块

    同步方法 public synchronized void add(int value){

    this.count += value;

    }

    注意到此处的Synchronized关键字是加在方法声明处,这会告诉JVM,它是一个同步方法。

    实例同步方法的锁,是加在拥有该方法的对象之上。因此每个实例的Synchronized关键字实际上都加在了不同的方法之上。同时只有一个线程能执行该实例的同步方法。

    同步静态方法 public static synchronized void add(int value){

    count += value;

    }

    上面是一个同步静态方法。同步静态方法的锁是加在类之上的,而相同的类在JVM中只有一个,一个类中只能有一个线程正在运行,不论它调用的是哪个静态方法。

    同步实例代码块 public void add(int value){

    synchronized(this){

    this.count += value;

    }

    }

    上面是一个非同步方法中的同步实例代码块。注意到同步代码块中Synchronized(this)中的this意味着当前实例对象。括号中的对象被称为监控对象。

    监控对象中只有一个线程能运行,下面的两个方法都把锁加在了当前的对象上,因此两者是等效的。线程每次只能执行其中的一个方法。如果第二个同步代码块把Synchronized加在不同的对象上,则这两个方法有可能被两个线程同时执行。 public class MyClass {

    // 同步方法

    public synchronized void log1(String msg1, String msg2){

    log.writeln(msg1);

    log.writeln(msg2);

    }

    // 同步代码块

    public void log2(String msg1, String msg2){

    synchronized(this){

    log.writeln(msg1);

    log.writeln(msg2);

    }

    }

    }

    静态方法中的同步代码

    下面的两个方法,都把锁加在类上。 public class MyClass {

    //静态同步方法

    public static synchronized void log1(String msg1, String msg2){

    log.writeln(msg1);

    log.writeln(msg2);

    }

    //静态同步代码块

    public static void log2(String msg1, String msg2){

    synchronized(MyClass.class){

    log.writeln(msg1);

    log.writeln(msg2);

    }

    }

    }

    一个JAVA同步的例子

    下面的这个例子,开启了两个线程,并且对同一个counter对象调用了add方法。每次只有一个线程能调用同一个实例的add方法,因为此处的Synchronized修饰的是对象。 // 柜员类

    public class Counter{

    long count = 0;

    // 此处有synchronized关键词修饰此实例方法

    public synchronized void add(long value){

    this.count += value;

    }

    }

    // 顾客类

    public class CounterThread extends Thread{

    protected Counter counter = null;

    public CounterThread(Counter counter){

    this.counter = counter;

    }

    public void run() {

    for(int i=0; i<10; i++){

    counter.add(i);

    }

    }

    }

    // 运行类

    public class Example {

    public static void main(String[] args){

    // 同一个counter实例

    Counter counter = new Counter();

    Thread threadA = new CounterThread(counter);

    Thread threadB = new CounterThread(counter);

    threadA.start();

    threadB.start();

    }

    }

    展开全文
  • 区别: ...同步方法使用关键字 synchronized修饰方法,而同步代码块主要修饰需要进行同步代码,用 synchronized(object){代码内容}进行修饰; 为何使用同步? java允许多线程并发控制,当多个线...

    区别:
    同步方法默认用this或者当前类class对象作为锁;
    同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,我们可以选择只同步会发生同步问题的部分代码而不是整个方法;
    同步方法使用关键字 synchronized修饰方法,而同步代码块主要是修饰需要进行同步的代码,用 synchronized(object){代码内容}进行修饰;

    为何使用同步?
    java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(增删改查),将会导致数据的不准确,相互之间产生冲突。类似于在atm取钱,银行数据确没有变,这是不行的,要存在于一个事务中。因此加入了同步锁,以避免在该线程没有结束前,调用其他线程。从而保证了变量的唯一性,准确性。
    1.同步方法:
    即有synchronized (同步,美 ['sɪŋkrənaɪzd] ) 修饰符修饰的方法。
    由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用给方法前,要获取内置锁,否则处于阻塞状态。
    例:public synchronized getMoney(){}
    注:synchronized修饰静态方法,如果调用该静态方法,将锁住整个类。

    2.同步代码块
    即有synchronized修饰符修饰的语句块,被该关键词修饰的语句块,将加上内置锁。实现同步。
    例:synchronized(Object o ){}

    同步是高开销的操作,因此尽量减少同步的内容。通常没有必要同步整个方法,同步部分代码块即可。
    同步方法默认用this或者当前类class对象作为锁。
    同步代码块可以选择以什么来加锁,比同步方法要更颗粒化,我们可以选择只同步会发生问题的部分代码而不是整个方法。

    展开全文
  • 同步代码块时 不是太明白同步和加锁,希望给个详细解释 同步和加锁含义是什么 怎样解释
  • 线程安全问题、同步代码块同步代码块的锁问题以及同步方法应用和问题、Lock、死锁问题 线程安全问题 ​ 前面讲解过电影院售票程序,从表面上看不出什么问题,但是在真实生活中, ​ 售票时网络不能实时...

    线程安全问题、同步代码块、同步代码块的锁问题以及同步方法的应用和锁问题、Lock锁、死锁问题

    线程安全问题

    ​ 前面讲解过电影院售票程序,从表面上看不出什么问题,但是在真实生活中,
    ​ 售票时网络是不能实时传输的,总是存在延迟的情况,所以,在出售一张票以后,需要一点时间的延迟
    ​ 每次卖票延迟100毫秒,此时就有可能出现同票或者负票的情况

    出现线程安全问题的前提条件:

    ​ 是否是多线程环境
    ​ 是否有共享数据
    ​ 是否有多条语句操作共享数据

    同步代码块解决线程安全问题

    格式:

    synchronized(对象){ //同步代码代码块上的锁,是一个互斥锁。
    死循环
    需要同步的代码;
    }

    这个同步代码块保证数据的安全性的一个主要因素就是这个对象
    注意这个对象 要定义为静态成员变量 才能被所有线程共享

    需要这个对象被所有的线程对象所共享

    这个对象其实就是一把锁.

    这个对象习惯叫做监视器

    
    
    public class CellRunnable implements Runnable{
        //这个票让三个线程共享
        static int piao=100;
        //确保这个锁对象,只有一个,多个线程公用一把锁
        static Object obj=new Object();
        @Override
        public void run() {
            while (true) {
             synchronized (obj){
                 if (piao >= 1) {
                     try {
                         Thread.sleep(50);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     System.out.println(Thread.currentThread().getName() + "正在出售第:" + (piao--) + " 张票");
                 }
             }
                //th1 执行完了,出了同步代码块,就会释放锁。释放锁了之后,多个线程再去争抢CPU的时间片
            }
        }
    }
    
    public class MyTest {
        public static void main(String[] args) {
            CellRunnable cellRunnable = new CellRunnable();
            Thread th1 = new Thread(cellRunnable, "窗口1");
            Thread th2 = new Thread(cellRunnable, "窗口2");
            Thread th3= new Thread(cellRunnable, "窗口3");
            th1.start();
            th2.start();
            th3.start();
        }
    }
    
    

    同步的好处: 同步的出现解决了多线程的安全问题。
    同步的弊端: 当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。

    java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。
    线程进入同步代码块或同步方法的时候会自动获得该锁,在退出同步代码块或同步方法时会释放该锁。
    获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。
    java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,
    当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,
    直到线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。

    同步方法解决线程安全问题

    同步方法使用的是对象锁

    java的对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,
    但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,
    类锁是用于类的静态方法或者一个类的class对象上的。
    我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,
    所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。
    但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,
    它只是用来帮助我们理解锁定实例方法和静态方法的区别的.

    
    public class CellRunnable implements Runnable{
        //这个票让三个线程共享
        static int piao=100;
        //确保这个锁对象,只有一个,多个线程公用一把锁
        static Object obj=new Object();
        int i=1;
        @Override
        public void run() {
            while (true) {
            if (i%2==0){
                synchronized (this){
                    //当th1这个线程进来同步代码块后,就持有了这个锁,其他线程没有持有锁,那么就要处于等待状态,等在同步代码块的外面
                    if (piao >= 1) {
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在出售第:" + (piao--) + " 张票");
                    }
                }
            }else{
                maipiao();
            }
            i++;
            }
        }
        //同步方法:我们可以把一个方法用synchronized这个关键字修饰,来封装一段代码,来解决线程安全问题
        //同步方法:默认用的锁对象是this
        private synchronized void maipiao() {
            //System.out.println(this);
            if (piao >= 1) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在出售第:" + (piao--) + " 张票");
            }
    
        }
    }
    
    public class MyTest {
        public static void main(String[] args) {
            //创建了一次任务 100
            CellRunnable cellRunnable = new CellRunnable();
            Thread th1 = new Thread(cellRunnable, "窗口1");
            Thread th2 = new Thread(cellRunnable, "窗口2");
            Thread th3= new Thread(cellRunnable, "窗口3");
            th1.start();
            th2.start();
            th3.start();
    
        }
    }
    
    

    静态同步方法解决线程安全问题

    静态同步方法使用的是类锁

    类的对象实例可以有很多个,但是每个类只有一个class对象,故可以保证锁只有一把

    
    public class CellRunnable implements Runnable{
        //这个票让三个线程共享
        static int piao=100;
        //确保这个锁对象,只有一个,多个线程公用一把锁
        static Object obj=new Object();
        int i=1;
        @Override
        public void run() {
            while (true) {
                //模拟一下真实的售票环境,有网络延迟。
            if (i%2==0){
                synchronized (CellRunnable.class){
                    //当th1这个线程进来同步代码块后,就持有了这个锁,其他线程没有持有锁,那么就要处于等待状态,等在同步代码块的外面
                    if (piao >= 1) {
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在出售第:" + (piao--) + " 张票");
                    }
                }
            }else{
                maipiao();
            }
            i++;
            }
        }
        //同步方法:我们可以把一个方法用synchronized这个关键字修饰,来封装一段代码,来解决线程安全问题
        //静态同步方法:默认用的锁对对象,用的是当前类的字节码对象
        private static synchronized void maipiao() {
            //System.out.println(this);
            if (piao >= 1) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在出售第:" + (piao--) + " 张票");
            }
    
        }
    }
    
    public class MyTest {
        public static void main(String[] args) {
            //创建了一次任务 100
            CellRunnable cellRunnable = new CellRunnable();
            Thread th1 = new Thread(cellRunnable, "窗口1");
            Thread th2 = new Thread(cellRunnable, "窗口2");
            Thread th3= new Thread(cellRunnable, "窗口3");
            th1.start();
            th2.start();
            th3.start();
        }
    }
    
    
    

    Lock锁

    Lock锁的概述
    虽然我们可以理解同步代码块和同步方法的锁对象问题,
    但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,
    为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

    Lock和ReentrantLock

    static ReentrantLock lock=new ReentrantLock();

    void lock() 加锁
    void unlock() 释放

    
    public class CellRunnable implements Runnable{
        //这个票让三个线程共享
        static int piao=100;
        //确保这个锁对象,只有一个,多个线程公用一把锁
        static ReentrantLock lock=new ReentrantLock();
        @Override
        public void run() {
            while (true) {
                //th1 th2 th3
                //加锁
                lock.lock();
                try{
                    if (piao >= 1) {
                        try {
                            //模拟一下真实的售票环境,有网络延迟。
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在出售第:" + (piao--) + " 张票");
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        }
    }
    
    public class MyTest {
        public static void main(String[] args) {
            //创建了一次任务 100
            CellRunnable cellRunnable = new CellRunnable();
            Thread th1 = new Thread(cellRunnable, "窗口1");
            Thread th2 = new Thread(cellRunnable, "窗口2");
            Thread th3= new Thread(cellRunnable, "窗口3");
            th1.start();
            th2.start();
            th3.start();
    
        }
    }
    
    

    死锁问题

    如果出现了同步嵌套,就容易产生死锁问题
    是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象

    死锁: 两个或者两个以上的线程,在抢占CPU的执行权的时候,都处于等待状态

    
    public interface ObjectUtils {
        //创建两个对象来充当两把锁
        public static final Object objA=new Object();
        public static final Object objB=new Object();
    }
    
    
    public class MyThread extends Thread{
        boolean flag;
    
        public MyThread(boolean flag) {
            this.flag=flag;
        }
    
        @Override
        public void run() {
            if (flag){
                synchronized (ObjectUtils.objA){
                    System.out.println("true 线程持有了objA锁,进来执行了AAAA");
                    synchronized (ObjectUtils.objB){
                        System.out.println("true 线程持有了objB锁,进来执行了BBB");
                    }
                }
            }else {
                synchronized (ObjectUtils.objB){
                    System.out.println("false线程持有了objB锁,进来执行BBB");
                    synchronized (ObjectUtils.objA){
                        System.out.println("false 线程持有了objA锁,进来执行了AAA");
                    }
                }
            }
        }
    }
    
    
    public class MyTest {
        public static void main(String[] args) {
            MyThread th1 = new MyThread(true);
            MyThread th2 = new MyThread(false);
            th1.start();
            th2.start();
        }
    }
    
    
    展开全文
  • 同步代码可以选择以什么来加锁,比同步方法更细颗粒化,同步代码可以同步有同步问题部分代码而不是整个方法。 同步方法用关键字synchronized修饰方法,同步代码主要修饰需要进行同步的代码块,用synchronized...

    同步方法默认用this或者当前类class对象作为锁。

    同步代码可以选择以什么来加锁,比同步方法更细颗粒化,同步代码可以同步有同步问题的部分代码而不是整个方法。

    同步方法用关键字synchronized修饰方法,同步代码主要修饰需要进行同步的代码块,用synchronized(object){代码内容}进行修饰。

    转载于:https://www.cnblogs.com/Freak-Lew/p/9196268.html

    展开全文
  • 1.同步代码块 synchronized(obj) { //obj表示同步监视器,同一个同步对象 /**..... TODO SOMETHING */ } class Singleton{ private static Singleton instance; public static Singleton getInstance(){ if...
  • 其语法如下:synchronized(obj){//同步代码块}其中obj就是同步监视器,它含义:线程开始执行同步代码块之前,必须先获得对同步监视器锁定。任何时刻只能有一个线程可以获得对同步监视器锁定,当同步代码块...
  • 同步方法使用关键字 synchronized修饰方法,而同步代码块主要修饰需要进行同步代码,用 synchronized(object){代码内容}进行修饰; 为何使用同步? java允许多线程并发控制,当多个线程同...
  • 普通代码块:位置在方法体内, 加速内存回收, 限定变量生命周期,及早释放无用变量 静态代码块:位置在类中方法体外, 只加载一次,只能调用静态修饰变量或方法 ...同步代码块:在代码块中公用一把 同步方法 ...
  • 里面有多线程同步锁的代码详解,开启了我对代码安全更深层次的认识,代码简单易懂。还有一个死锁的demo,现在经过修改后贴在自己园里,供理解其思想。 举一个线程作用的例子: 一个Java虚拟机的实例运行在一个单独...
  • 同步代码块或同步方法执行过程怎样???线程同步有什么优缺点??? 完成:第一遍 1.synchronized关键字有什么作用??? synchronized两种方式:同步代码块、同步方法 被synchronized包围代码块,称为同步...
  • 什么是同步代码块(Synchronized Block)同步代码块简单来说就是将一段代码用一把锁给锁起来, 只有获得了这把锁的线程才访问, 并且同一时刻, 只有一个线程能持有这把锁, 这样就保证了同一时刻只有一个线程能执行被锁住...
  • 同步代码块在方法内部使用 synchronized 加锁对象相同的话,同步方法锁的范围大于等于同步方法块。一般加锁范围越大,性能越差 同步方法如果 static 方法,等同于同步方法块加锁在该 Class 对象上 【Java...
  • java 中同步方法和同步代码块的区别详解在Java语言中,每一个对象有一把。线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别(粗粒度)或者代码块级别(细粒度)。问题...
  • 同步代码块

    2020-02-06 10:49:40
    同步代码块 1.什么情况下需要同步 当多线程并发,有多段代码同时执行时,我们希望某一段代码执行过程中CPU不要切换到其他线程工作,这时就需要同步。...多个同步代码块如果使用相同的锁对象,那么他...
  • 问题这样,我在看书时没想明白,就是执行sleep(50)这句话后两个线程就不同步了,去掉sleep(50)后线程同步,我想了一下这关系到线程什么时候确定synchronized内的锁对象,求大神解释!!!!
  • 同步代码块的使用

    2017-05-31 17:50:49
    1.什么情况下需要同步 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行过程中CPU不要切换... 使用synchronized关键字加上一个对象来定义一段代码, 这就叫同步代码块 多个同步代码块如果使用相同
  • 什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程三种方式示例代码中,实现Runnable创建多条线程,输出中结果中会有错误,比如一张票卖了两次,有票没卖...用同步代码块改写上面代码 package testpa...
  • Java同步代码块

    2019-06-05 14:36:23
    同步代码块是共用同一把锁的代码块,使用同步代码块可以实现两块代码在执行过程中互斥。 即执行代码块A的时候不执行代码块B,执行代码块B的时候不执行代码块A。 实现方法: 使用静态对象锁。 private static ...
  • 为何要使用同步? java允许多线程并发控制,当多个线程同时操作...同步方法和同步代码块的区别是什么? 同步方法默认用this或者当前类class对象作为同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,...
  • 同步代码块(Synchronized Block) java中最基础的实现线程间的同步与通信的机制之一,本篇我们将对同步代码块以及监视器锁的概念进行讨论。 系列文章目录 什么是同步代码块(Synchronized Block) 同步代码块简单...
  • 什么使用synchronize关键字:  存在共享数据,且此数据涉及多线程操作。(如经典的多窗口卖票的例子) ...无论是同步代码块还是同步方法,在同一实例中都能达到上锁的效果。 在不同实例中: ...
  • 同步方法默认用this或者当前... 同步代码块可以选择以什么来加锁,比同步方法更细颗粒度,我们可以选择只同步会发生同步问题部分代码而不是整个方法。 转载于:https://www.cnblogs.com/fanvfan/p/7565316.html...
  • 同步代码块(Synchronized Block) java中最基础的实现线程间的同步与通信的机制之一,本篇我们将对同步代码块以及监视器锁的概念进行讨论。 系列文章目录 什么是同步代码块(Synchronized Block) 同步代码块简单来说...
  • 什么是同步 同步就是加锁,不让其它人访问 synchronized指就是同步意思 什么情况下需要同步 ...当多线程并发, 我们希望某一段代码执行过程中CPU不要切换到...多个同步代码块如果使用相同的锁对象, 那么他...
  • 同步方法指 多个线程访问一个方法 则第二个或者之后访问这个方法线程阻塞 直到第一个线程释放后才能依次访问, ...而同步代码块在方法内部中加锁,相对来说同步代码块的范围比较小,则范围越小 性能越好。 ...
  • java 中同步方法和同步代码块的区别详解 在Java语言中,每一个对象有一把。线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别(粗粒度)或者代码块级别(细粒度)。 ...
  • **什么时候需要同步? 1.当多线程并发,有多段代码同时执行时,我们希望某一段代码执行过程中CPU不要切换到其他线程工作,这时就需要同步。...2.多个同步代码块如果使用相同的锁对象,那么他们就...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 865
精华内容 346
关键字:

同步代码块锁的是什么