精华内容
下载资源
问答
  • 最近就在折腾和相关的东西:首先呢,作为的对象,我们最好定义为final,因为这样对象就不会发生变化,因此最终会只有一个,不同线程竞争一个,就可以达成同步效果了。针对不同情况,也应该相应进行调整,...

    最近就在折腾和锁相关的东西:

    首先呢,作为锁的对象,我们最好定义为final,因为这样对象就不会发生变化,因此最终锁会只有一个,不同线程竞争一个锁,就可以达成同步效果了。

    针对不同情况,锁也应该相应进行调整,这具体和线程影响的范围有关系,只需要通过锁限制会有多线程问题的部分即可,例如我们有多个地区的店一起卖票,当然,不同地区的票就没有线程问题,因此我们可以使用多个对象作为锁,分别锁定各个地区,这样既能够保证执行效率,又能达到同步的目的。

    这里的ticket,他是一个包装类型,既可以作为数值直接运算,也可以作为Object调用各类方法,在java处理的时候,会自动变成基本类型,这个过程叫做自动拆箱,而当我们对包装类型直接使用数值赋值的时候,java会自动转换他为包装类型,这个过程叫做自动装箱。

    这样做的目的是因为java是面向对象的,一旦基本类型装箱,就会成为引用类型,同时具有引用类型的所有性质,这样你就能够使用这个类型的各种方法了,而基本类型你是无法使用他的方法的。

    当然同时这种包装类型也是特殊的,他同样具有基本类型的特点,例如可以直接进行运算等。

    关于这个对象,到底是一个新对象还是固定的对象,我本身不是很了解,不过看其他答主已经验证了这个问题了,他的确是一个新对象。

    同时呢,Java的锁并不止一个synchronize关键字,他提供了很多其他的锁,你同样可以通过这锁来完成同步的工作。

    另外关于字符串,字符串其实是一个常量,直接锁定某个字符串的话,通常情况下是能够进行同步的,如果通过new创建的字符串,那将会是一个新的对象,即使你new了内容相同的字符串,那也是两个,而直接双引号,那就是常量了。

    其实这里你可以直接private static final Object locker = new Object();

    然后通过locker这个量进行同步即可。

    展开全文
  • 同步代码块1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块。其语法如下:synchronized(obj){//同步代码块}其中obj就是同步监视器...

    一 同步代码块

    1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块。其语法如下:

    synchronized(obj){

    //同步代码块

    }

    其中obj就是同步监视器,它的含义是:线程开始执行同步代码块之前,必须先获得对同步监视器的锁定。任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对该同步监视器的锁定。虽然java程序允许使用任何对象作为同步监视器,但 是同步监视器的目的就是为了阻止两个线程对同一个共享资源进行并发访问,因此通常推荐使用可能被并发访问的共享资源充当同步监视器。

    2.小例子

    Account.java

    public classAccount {privateString accountNo;private doublebalance;public Account(String accountNo,doublebalance){this.accountNo=accountNo;this.balance=balance;

    }public doublegetBalance() {returnbalance;

    }public void setBalance(doublebalance) {this.balance =balance;

    }publicString getAccountNo() {returnaccountNo;

    }public voidsetAccountNo(String accountNo) {this.accountNo =accountNo;

    }

    @Overridepublic booleanequals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;

    Account account=(Account) o;returnaccountNo.equals(account.accountNo);

    }

    @Overridepublic inthashCode() {returnaccountNo.hashCode();

    }

    }

    DrawThread.java

    public class DrawThread extendsThread {privateAccount account;private doubledrawAmount;public DrawThread(String name, Account account, doubledrawAmount) {super(name);this.account =account;this.drawAmount =drawAmount;

    }public voidrun(){synchronized(account){if(account.getBalance()>=drawAmount){

    System.out.println(getName()+ "取钱成功,吐出钞票: " +drawAmount);try{

    Thread.sleep(1);

    }catch(InterruptedException ex){

    ex.getStackTrace();

    }

    account.setBalance(account.getBalance()-drawAmount);

    System.out.println("\t余额为:"+account.getBalance());

    }else{

    System.out.println(getName()+"取钱失败,余额不足");

    }

    }

    }

    }

    DrawTest.java

    public classDrawTest {public static voidmain(String[] args){

    Account acct=new Account("1234567",1000);new DrawThread("甲",acct,800).start();new DrawThread("乙",acct,800).start();

    }

    }

    甲取钱成功,吐出钞票: 800.0

    余额为:200.0

    乙取钱失败,余额不足

    3.如果将DrawThread的同步去掉:

    public class DrawThread extendsThread {privateAccount account;private doubledrawAmount;public DrawThread(String name, Account account, doubledrawAmount) {super(name);this.account =account;this.drawAmount =drawAmount;

    }public voidrun(){//synchronized (account){

    if(account.getBalance()>=drawAmount){

    System.out.println(getName()+ "取钱成功,吐出钞票: " +drawAmount);try{

    Thread.sleep(1);

    }catch(InterruptedException ex){

    ex.getStackTrace();

    }

    account.setBalance(account.getBalance()-drawAmount);

    System.out.println("\t余额为:"+account.getBalance());

    }else{

    System.out.println(getName()+"取钱失败,余额不足");

    }//}

    }

    }

    会出现这些情况的结果:

    乙取钱成功,吐出钞票: 800.0

    甲取钱成功,吐出钞票: 800.0

    余额为:200.0

    余额为:-600.0

    甲取钱成功,吐出钞票: 800.0

    乙取钱成功,吐出钞票: 800.0

    余额为:200.0

    余额为:200.0

    程序使用synchronized将run()方法里的方法体修改成同步代码块,同步监视器就是account对象,这样的做法符合“加锁-修改-释放锁”的逻辑,这样就可以保证并发线程在任一时刻只有一个线程进入修改共享资源的代码区。多次运行,结果只有一个。

    二 同步方法

    1.同步方法就是使用synchronized关键字修饰某个方法,这个方法就是同步方法。这个同步方法(非static方法)无须显式指定同步监视器,同步方法的同步监视器是this,也就是调用该方法的对象。通过同步方法可以非常方便的实现线程安全的类,线程安全的类有如下特征:

    该类的对象可以方便的被多个线程安全的访问;

    每个线程调用该对象的任意方法之后都能得到正确的结果;

    每个线程调用该对象的任意方法之后,该对象状态依然能保持合理状态。

    2.不可变类总是线程安全的,因为它的对象状态不可改变可变类需要额外的方法来保证其线程安全,在Account类中我们只需要把balance的方法变成同步方法即可。

    Account.java

    public classAccount {privateString accountNo;private doublebalance;public Account(String accountNo,doublebalance){this.accountNo=accountNo;this.balance=balance;

    }//因为账户余额不可以随便更改,所以只为balance提供getter方法

    public doublegetBalance() {returnbalance;

    }publicString getAccountNo() {returnaccountNo;

    }public voidsetAccountNo(String accountNo) {this.accountNo =accountNo;

    }

    @Overridepublic booleanequals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;

    Account account=(Account) o;returnaccountNo.equals(account.accountNo);

    }

    @Overridepublic inthashCode() {returnaccountNo.hashCode();

    }//提供一个线程安全的draw()方法来完成取钱操作

    public synchronized void draw(doubledrawAmount){if(balance>=drawAmount){

    System.out.println(Thread.currentThread().getName()+"取钱成功!吐出钞票:"+drawAmount);try{

    Thread.sleep(1);

    }catch(InterruptedException ex){

    ex.printStackTrace();

    }

    balance-=drawAmount;

    System.out.println("\t余额为:"+balance);

    }else{

    System.out.println(Thread.currentThread().getName()+"取钱失败,余额不足");

    }

    }

    }

    DrawThread.java

    public class DrawThread extendsThread {privateAccount account;private doubledrawAmount;public DrawThread(String name, Account account, doubledrawAmount) {super(name);this.account =account;this.drawAmount =drawAmount;

    }public voidrun(){

    account.draw(drawAmount);

    }

    }

    DrawTest.java

    public classDrawTest {public static voidmain(String[] args){

    Account acct=new Account("1234567",1000);new DrawThread("甲",acct,800).start();new DrawThread("乙",acct,800).start();

    }

    }

    注意,synchronized可以修饰方法,修饰代码块,但是不能修饰构造器、成员变量等。在Account类中定义draw()方法,而不是直接在 run()方法中实现取钱逻辑,这种做法更符合面向对象规则。DDD设计方式,即Domain Driven Design(领域驱动设计),认为每个类都应该是完备的领域对象,Account代表用户账户,就应该提供用户账户的相关方法。通过draw()方法来执行取钱操作,而不是直接将setBalance()方法暴露出来任人操作。

    但是,可变类的线程安全是以降低程序的运行效率为代价的,不要对线程安全类的所有方法都进行同步,只对那些会改变竞争资源(共享资源)的方法进行同步。同时,可变类有两种运行环境:单线程环境和多线程环境, 则应该为可变类提供两种版本,即线程安全版本和线程不安全版本。如JDK提供的StringBuilder在单线程环境下保证更好的性能,StringBuffer可以保证多线程安全。

    三 释放同步监视器的锁定

    1.任何线程进入同步代码块,同步方法之前,必须先获得对同步监视器的锁定,那么如何释放对同步监视器的锁定呢,线程会在一下几种情况下释放同步监视器:

    当前线程的同步方法、同步代码块执行结束,当前线程即释放同步监视器;

    当前线程在同步代码块、同步方法中遇到break,return终止了该代码块、方法的继续执行;

    当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致了该代码块、方法的异常结束;

    当前线程执行同步代码块或同步方法时,程序执行了同步监视器对象的wait()方法,则当前线程暂停,并释放同步监视器;

    2.以下几种情况,线程不会释放同步监视器:

    线程执行同步代码块或同步方法时,程序调用Thread.sleep(),Thread.yield()方法来暂停当前线程的执行,当前线程不会释放同步监视器;

    线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放同步监视器,当然,程序应尽量避免使用suspend()和resume()方法来控制线程。

    四 同步锁:

    1.Java5开始,Java提供了一种功能更加强大的线程同步机制——通过显式定义同步锁对象来实现同步,这里的同步锁由Lock对象充当。

    Lock 对象提供了比synchronized方法和synchronized代码块更广泛的锁定操作,Lock是控制多个线程对共享资源进行访问的工具。通常, 锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应该先获得Lock对象。

    某些锁可能允许对共享资源并发访问,如ReadWriteLock(读写锁),Lock,ReadWriteLock是Java5提供的两个根接口,并为 Lock提供了ReentrantLock实现类,为ReadWriteLock提供了ReentrantReadWriteLock实现类。在 Java8中提供了新型的StampLock类,在大多数场景下它可以替代传统的ReentrantReadWriteLock。 ReentrantReadWriteLock为读写操作提供了三种锁模式:Writing,ReadingOptimistic,Reading。

    2.在实现线程安全的控制中,比较常用的是ReentrantLock(可重入锁)。主要的代码格式如下:

    classX{//定义锁对象

    private final ReentrantLock lock=newReentrantLock();//定义需要保证线程安全的方法

    public voidm(){//加锁

    lock.lock();try{//...method body

    }//使用finally块来保证释放锁

    finally{

    lock.unlock();

    }

    }

    }

    将Account.java修改为:

    public classAccount {private final ReentrantLock lock=newReentrantLock();privateString accountNo;private doublebalance;public Account(String accountNo,doublebalance){this.accountNo=accountNo;this.balance=balance;

    }//因为账户余额不可以随便更改,所以只为balance提供getter方法

    public doublegetBalance() {returnbalance;

    }publicString getAccountNo() {returnaccountNo;

    }public voidsetAccountNo(String accountNo) {this.accountNo =accountNo;

    }

    @Overridepublic booleanequals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;

    Account account=(Account) o;returnaccountNo.equals(account.accountNo);

    }

    @Overridepublic inthashCode() {returnaccountNo.hashCode();

    }//提供一个线程安全的draw()方法来完成取钱操作

    public void draw(doubledrawAmount){//加锁

    lock.lock();try{if (balance >=drawAmount) {

    System.out.println(Thread.currentThread().getName()+ "取钱成功!吐出钞票:" +drawAmount);try{

    Thread.sleep(1);

    }catch(InterruptedException ex) {

    ex.printStackTrace();

    }

    balance-=drawAmount;

    System.out.println("\t余额为:" +balance);

    }else{

    System.out.println(Thread.currentThread().getName()+ "取钱失败,余额不足");

    }

    }finally{

    lock.unlock();

    }

    }

    }

    使用Lock与使用同步代码有点相似,只是使用Lock时可以显式使用Lock对象作为同步锁,而使用同步方法时系统隐式使用当前对象作为同步监视器。使用 Lock时每个Lock对象对应一个Account对象,一样可以保证对于同一个Account对象,同一个时刻只能有一个线程进入临界区。Lock提供 了同步方法和同步代码块所没有的其他功能,包括使用非块结构的tryLock()方法,以及试图获取可中断锁的lockInterruptibly()方法,还有获取超时失效锁的tryLock(long,TimeUnit)方法。

    ReentrantLock可重入锁的意思是,一个线程可以对已被加锁的ReentrantLock锁再次加锁,ReentrantLock对象会维持一个计数器来追踪lock()方法的嵌套调用,线程在每次调用lock()加锁后,必须显式调用unlock()来释放锁,所以一段被锁保护的代码可以调用另一个被相同锁保护的方法。

    五 死锁

    当两个线程相互等待对方释放同步监视器时就会发生死锁,Java虚拟机没有检测,也没有采取措施来处理死锁情况,所以多线程编程时应该采取措施避免死锁出现。一旦出现死锁,程序既不会发生任何异常,也不会给出任何提示,只是所有线程都处于阻塞状态,无法继续。

    如DeadLock.java

    classA{public synchronized voidfoo(B b){

    System.out.println("当前线程名为:"+Thread.currentThread().getName()+"进入了A实例的foo()方法");try{

    Thread.sleep(200);

    }catch(InterruptedException ex){

    ex.printStackTrace();

    }

    System.out.println("当前线程名为:"+Thread.currentThread().getName()+"试图调用B实例的last()方法");

    b.last();

    }public synchronized voidlast(){

    System.out.println("进入了A类的last()方法内部");

    }

    }classB{public synchronized voidbar(A a){

    System.out.println("当前线程名为:"+Thread.currentThread().getName()+"进入了B实例的bar()方法");try{

    Thread.sleep(200);

    }catch(InterruptedException ex){

    ex.printStackTrace();

    }

    System.out.println("当前线程名为:"+Thread.currentThread().getName()+"试图调用A实例的last()方法");

    a.last();

    }public synchronized voidlast(){

    System.out.println("进入了B类的last()方法内部");

    }

    }public class DeadLock implementsRunnable{

    A a=newA();

    B b=newB();public voidinit(){

    Thread.currentThread().setName("主线程");

    a.foo(b);

    System.out.println("进入了主线程之后...");

    }public voidrun(){

    Thread.currentThread().setName("副线程");

    b.bar(a);

    System.out.println("进入了副线程之后...");

    }public static voidmain(String[] args){

    DeadLock d1=newDeadLock();newThread(d1).start();

    d1.init();

    }

    }

    结果:

    当前线程名为:主线程进入了A实例的foo()方法

    当前线程名为:副线程进入了B实例的bar()方法

    当前线程名为:主线程试图调用B实例的last()方法

    当前线程名为:副线程试图调用A实例的last()方法

    展开全文
  • /** 同步函数的使用的是this** 同步函数和同步代码块的区别:* 同步函数的是固定的this。** 同步代码块是任意的对象** 建议使用同步代码块*/class Ticket_1 implements Runnable{private int num = 400;...

    /*

    * 同步函数的使用的锁是this

    *

    * 同步函数和同步代码块的区别:

    * 同步函数的锁是固定的this。

    *

    * 同步代码块的锁是任意的对象

    *

    * 建议使用同步代码块

    */

    class Ticket_1 implements Runnable{

    private int num = 400;

    Object obj = new Object();

    boolean flag = true;

    public  void run(){

    if(flag)

    while(true)

    {

    synchronized(obj){

    if(num > 0){

    try{

    Thread.sleep(10);

    }

    catch(InterruptedException e){}

    System.out.println(Thread.currentThread().getName() + “……block……..” + num–);

    }

    }

    }

    else

    while(true)

    this.show();

    }

    public synchronized void show(){

    if(num > 0){

    try{

    Thread.sleep(10);

    }

    catch(InterruptedException e){}

    System.out.println(Thread.currentThread().getName() + “…….function….” + num–);

    }

    }

    }

    public class SynThreadDemo {

    /**

    * @param args

    */

    public static void main(String[] args) {

    // TODO Auto-generated method stub

    Ticket_1 t = new Ticket_1();

    Thread t1 = new Thread(t);

    Thread t2 = new Thread(t);

    Thread t3 = new Thread(t);

    Thread t4 = new Thread(t);

    t1.start();

    try{

    Thread.sleep(10);

    }catch(InterruptedException e){

    System.out.println(Thread.currentThread().getName() + “………….”);

    }

    t.flag = false;

    t2.start();

    //t3.start();

    //t4.start();

    }

    }

    =================================================================================================================================

    /*

    * 静态的同步函数使用的锁是该函数所属字节码文件对象

    * 可以用getClass方法获取 也可以用当前 类名.class表示

    *

    */

    class Ticket_2 implements Runnable{

    private static int num = 200;

    //Object obj = new Object();

    boolean flag = true;

    public  void run(){

    if(flag)

    while(true)

    {

    synchronized(Ticket_2.class)//(this.getClass())

    {

    if(num > 0){

    try{

    Thread.sleep(10);

    }

    catch(InterruptedException e){}

    System.out.println(Thread.currentThread().getName() + “……block……..” + num–);

    }

    }

    }

    else

    while(true)

    this.show();

    }

    public static synchronized void show(){

    if(num > 0){

    try{

    Thread.sleep(10);

    }

    catch(InterruptedException e){}

    System.out.println(Thread.currentThread().getName() + “…….function….” + num–);

    }

    }

    }

    public class StaticSynFunction {

    // TODO Auto-generated method stub

    public static void main(String[] args) {

    // TODO Auto-generated method stub

    Ticket_2 t = new Ticket_2();

    Thread t1 = new Thread(t);

    Thread t2 = new Thread(t);

    Thread t3 = new Thread(t);

    Thread t4 = new Thread(t);

    t1.start();

    try{

    Thread.sleep(10);

    }catch(InterruptedException e){

    System.out.println(Thread.currentThread().getName() + “………….”);

    }

    t.flag = false;

    t2.start();

    //t3.start();

    //t4.start();

    }

    }

    展开全文
  • /*** @author admin* @date 2018/1/12 9:48* 做用在同一个实例对象上讨论* synchronized同步方法的测试* 两个线程,一个线程调用synchronized修饰方法,另外一个线程能够调用非synchronized修饰的方法,互不影响*/...

    /**

    * @author admin

    * @date 2018/1/12 9:48

    * 做用在同一个实例对象上讨论

    * synchronized同步方法的测试

    * 两个线程,一个线程调用synchronized修饰方法,另外一个线程能够调用非synchronized修饰的方法,互不影响

    */

    public class SynchronizedTest {

    public synchronized void methodA() {

    try {

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

    System.out.println("methodA-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    public void methodB() {

    try {

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

    System.out.println("methodB-" + i );

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    public static void main(String[] args) {

    SynchronizedTest test = new SynchronizedTest();

    Thread thread1 = new Thread(new Runnable() {

    @Override

    public void run() {

    test.methodA();

    }

    });

    thread1.start();

    Thread thread2 = new Thread(new Runnable() {

    @Override

    public void run() {

    test.methodB();

    }

    });

    thread2.start();

    }

    }

    运行结果:

    methodA-0

    methodB-0

    methodA-1

    methodB-1

    methodB-2

    methodA-2

    methodA-3

    methodB-3

    methodA-4

    methodB-4

    /**

    * @author admin

    * @date 2018/1/12 10:16

    * 做用在同一个实例对象上讨论

    * Sychronized代码块的测试

    * 两个线程,一个线程执行synchronized代码块,另外一个线程执行非synchronized代码块

    */

    public class SychronizedTest2 {

    public void methodA() {

    synchronized (this) {

    try {

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

    System.out.println("methodA-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    public void methodB() {

    try {

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

    System.out.println("methodB-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    public static void main(String[] args) {

    SychronizedTest2 test2 = new SychronizedTest2();

    Thread thread1 = new Thread(new Runnable() {

    @Override

    public void run() {

    test2.methodA();

    }

    });

    thread1.start();

    Thread thread2 = new Thread(new Runnable() {

    @Override

    public void run() {

    test2.methodB();

    }

    });

    thread2.start();

    }

    }

    运行结果:

    methodA-0

    methodB-0

    methodA-1

    methodB-1

    methodA-2

    methodB-2

    methodB-3

    methodA-3

    methodA-4

    methodB-4

    /**

    * @author admin

    * @date 2018/1/12 10:33

    * 做用在同一个实例对象上讨论

    * Synchronized同步方法和同步代码块

    * 一、synchronized和synchronized(this)两者没区别,都做用在this对象锁上面,因此会同步

    * 二、synchronized(obj),这个是做用在obj对象锁上面,和this对象锁不一样,因此不会同步

    */

    public class SynchronizedTest3 {

    public synchronized void methodA() {

    try {

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

    System.out.println("methodA-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    public void methodB() {

    synchronized (this) {

    try {

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

    System.out.println("methodB-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    public void methodC() {

    Object obj = new Object();

    synchronized (obj) {

    try {

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

    System.out.println("methodC-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    public static void main(String[] args) {

    SynchronizedTest3 test3 = new SynchronizedTest3();

    Thread thread1 = new Thread(new Runnable() {

    @Override

    public void run() {

    test3.methodA();

    }

    });

    thread1.start();

    Thread thread2 = new Thread(new Runnable() {

    @Override

    public void run() {

    test3.methodB();

    }

    });

    thread2.start();

    Thread thread3 = new Thread(new Runnable() {

    @Override

    public void run() {

    test3.methodC();

    }

    });

    thread3.start();

    }

    }

    运行结果:

    methodA-0

    methodC-0

    methodA-1

    methodC-1

    methodA-2

    methodC-2

    methodA-3

    methodC-3

    methodA-4

    methodC-4

    methodB-0

    methodB-1

    methodB-2

    methodB-3

    methodB-4

    /**

    * @author admin

    * @date 2018/1/12 10:48

    * 做用在同一个类上讨论,每个类只有一个类锁

    * synchronized类锁

    * static synchronized 和 synchronized(SynchronizedTest4.class),都是做用在同一个类锁上,因此会同步

    */

    public class SynchronizedTest4 {

    public synchronized static void methodA() {

    try {

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

    System.out.println("methodA-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    public void methodB() {

    synchronized (SynchronizedTest4.class) {

    try {

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

    System.out.println("methodB-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    public static void main(String[] args) {

    SynchronizedTest4 test4 = new SynchronizedTest4();

    Thread thread1 = new Thread(new Runnable() {

    @Override

    public void run() {

    test4.methodA();

    }

    });

    thread1.start();

    Thread thread2 = new Thread(new Runnable() {

    @Override

    public void run() {

    test4.methodB();

    }

    });

    thread2.start();

    }

    }

    运行结果:

    methodA-0

    methodA-1

    methodA-2

    methodA-3

    methodA-4

    methodB-0

    methodB-1

    methodB-2

    methodB-3

    methodB-4

    /**

    * @author admin

    * @date 2018/1/12 11:03

    * synchronized的对象锁和static synchronized的类锁,是两个不一样的锁,因此不会同步

    * 两个线程,一个调用对象锁,一个调用类锁

    */

    public class SynchronizedTest5 {

    public synchronized void methodA() {

    try {

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

    System.out.println("methodA-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    public synchronized static void methodB() {

    try {

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

    System.out.println("methodB-" + i);

    Thread.sleep(1000);

    }

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    public static void main(String[] args) {

    SynchronizedTest5 test5 = new SynchronizedTest5();

    Thread thread1 = new Thread(new Runnable() {

    @Override

    public void run() {

    test5.methodA();

    }

    });

    thread1.start();

    Thread thread2 = new Thread(new Runnable() {

    @Override

    public void run() {

    test5.methodB();

    }

    });

    thread2.start();

    }

    }

    运行结果:

    methodA-0

    methodB-0

    methodA-1

    methodB-1

    methodB-2

    methodA-2

    methodB-3

    methodA-3

    methodB-4

    methodA-4

    展开全文
  • 同步代码块与隐式

    2021-03-06 23:23:06
    在上一节中,我们通过以下代码完成多个线程对共享资源的竞争问题。synchronized(ThreadCompetitionDemo.class...同步代码块的标准语法如下:synchronized(对象){...}synchronized关键字的作用就是用于声明这是一段...
  • 什么会出现同步处理? 如果要写一个多个线程卖票的代码,按照原本思路代码如下: class MythreadB implements Runnable { private Integer tickets=10; public void run() { ...
  • 同步块在Java中是同步在某个对象上,事实上在java中,任何一个对象都可以作为一个。所有同步在一个对象上的同步块在同时只能被一个线程进入并执行操作。所有其他等待进入该同步块的线程将被阻塞,直到执行该同步块...
  • Java之同步代码块

    2021-02-26 17:43:31
    Java多线程的同步代码块synchronized(对象){需要同步的代码}同步代码块可以解决安全问题的根本原因在于那个对象快上,这个对象如同的功能。多个线程需要同一个,才能的住,所以这个对象需要在run()方法外面...
  • Java 同步代码块

    2021-03-17 19:42:31
    public class ThreadDemo5 {public static void main(String[] args) {//开启四个线程 实现资源共享的目的TestThread4 testThread4 = new TestThread4();Thread thread = new Thread...//资源数据访问不同步new Th...
  • 同步代码块执行完毕,释放open 5)第二个线程也再次获取cpu,来到了同步代码块,发现同步监视器open状态,拿到并且上,由阻塞状态进入就绪状态,再进入运行状态,重复第一个线程的处理过程(加锁) 强调:同步...
  • 那么同步方法和同步代码块的区别是什么呢?我们用代码来研究一下。准备工作首先我们准备一个测试类ClassLock。public class ClassLock {public static void main(String[] args) {ClassLock classLock1 = new Class...
  • 线程同步问题大都使用synchronized解决,有同步代码块和同步方法的两种方式,主要记一下这两种的区别测试代码:1 packagecom.xujingyang.testThread;23 public classSynObj{4 public synchronized voidshowA(){5 System...
  • 文章目录前言一、同步代码块解决线程安全问题二、同步方法解决线程安全问题三、Lock解决线程安全问题 前言 我们首先使用学习到的多线程知识,模拟电影票售票过程,引出线程安全问题。 /* 需求:某电影院目前...
  • java相关:浅谈同步监视器之同步代码块、同步方法发布于 2021-1-19|复制链接下面小妖就为大家带来一篇浅谈同步监视器之同步代码块、同步方法。小妖觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小妖...
  • 当不使用代码锁的时候是不能够保证线程的安全性问题的,不使用安全的时候有时候可能会出现很多问题,例如常见的问题有: 次序的扰乱: 我们经常会看到卖票等程序买的票数的张数不是紧挨着卖的,而是多个线程可能买...
  • 当两个或多个并发线程访问同一个对象中的synchronsized方法(或...话不多说看示例:synchronized同步代码块示例Task.javapublic class Task {private String getData1;private String getData2;public synchronize...
  • Java多线程同步代码块

    2021-02-28 19:26:06
    因为程序在运行时,会出现一个线程在判断条件满足后,具备了执行资格,但没有运行代码后一个线程也判断了条件,也具备了执行资格,后一个线程运行了代码,但这时候,线程运行的条件不满足了这时候,就出现了安全问题...
  • 今天发现自己写的线上程序出现数据库不能同步的问题,查看日志已经停止记录,随后使用jstack查看线程的运行状况,发现有个同步线程住了。以下是jstack -l637 问题线程的内容。"schedulerJob-t-291" #314 daemon ...
  • 给其它持有该的对象用,其它对象用完后再636f707962616964757a686964616f31333337396235告知(notify)等待的那个对象可以继续执行了,因此,只有在synchronized中才有意义(否则,如果大家并不遵循同步机制,那还...
  • Java 慎用方法级别的synchronized关键字为什么要这么说呢, 因为笔者被这个坑过(其实是自己坑自己)╮(╯_╰)╭先看一段synchronized的详解:synchronized 是 java语言的关键字,当它用来修饰一个方法或者一个代码块...
  • Java 多线程 —— 同步代码块(解决线程安全问题)

    千次阅读 多人点赞 2021-10-23 19:59:26
    目录火车站抢票问题同步代码块同步方法(this)同步方法,在public的后面加上synchronized关键字this静态同步方法 火车站抢票问题 由于现实中买票也不会是零延迟的,为了真实性加入了延迟机制,也就是线程休眠...
  • 1)线程同步机制简介 2)的概念 2.1)的实现方式 2.2)的作用 2.3)相关的概念 3)内部:synchronized关键字 ...3.1)synchronized同步代码块 3.2)同步方法 3.3)同步静态方法 4)死锁
  • 1. 修饰一个代码块,被修饰的代码块称为同步语句块,作用的对象是调用这个代码块的对象,其作用的范围有以下两种情况; synchronized(SynchronizedTest .class)为类,则无论是都相同对象调用都为同步阻塞. ...
  • java 中同步方法和同步代码块的区别详解在Java语言中,每一个对象有一把。线程可以使用synchronized关键字来获取对象上的。synchronized关键字可应用在方法级别(粗粒度)或者是代码块级别(细粒度)。问题的...
  • 其次,在同步代码块中,我们可以自由的选择任何一个java对象实例作为同步过程中要使用到的。但是对于实例同步方法而言,这个是不能选择的,就是这个对象实例。对于静态同步方法而言,这个就是类的class对象...
  • 同步代码块 如何解决线程安全问题呢? 前面我们已经说过了解决思路:对于多条共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。 为了解决这个问题,Java的多线程支持引入同步监视器...
  • 1.synchronized同步关键字 这里涉及到多个线程对共享资源进行处理,这里就必须要给线程“排队”,使用的关键字是synchronized(同步),在...lock是一个对象,它是同步代码块的关键。当线程执行同步代码块时,首先
  • 同步代码块 语法: 使用方法: 示例: package com.ycy5; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SellTicket implements Runnable{ private ...
  • 线程安全问题其实就是由多个线程同时处理共享资源所导致的。 要想解决线程安全问题,必须得保证下面用于处理共享资源的代码在...上面的代码中, lock 是—个对象,它是同步代码块的关键。当线程执行同步代码块时,首先会

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 192,694
精华内容 77,077
关键字:

同步代码块锁的是什么