为了账号安全,请及时绑定邮箱和手机立即绑定

同步方法和对象锁

同步方法和对象锁

桃花长相依 2022-06-04 15:34:23
根据我的阅读和理解,每个对象都有在尝试访问同步方法时发生的锁定。这是我的代码(在 2 个不同的类文件中):public class test { public synchronized void inc1( String who ) {         for( int i = 0 ; i < 1500 ; i++ )             System.out.println( who+": "+i ); }}public class testsyn implements Runnable {    test k = new test( );    public static void main( String[ ] args )    {        new Thread( new testsyn( ) ).start( );        new testsyn( ).doStuff( );    }    public void doStuff( ) { k.inc1( "Main" ); }    public void run( )    {        k.inc1( "Thread" );    }}所以假设我的输出的第一行是:“Main:0”。这意味着主线程已经获取了名为“k”的测试对象的密钥,对吧?我创建的另一个线程怎么可能在主线程完成之前进入“inc1”方法并打印输出?我注意到这个问题发生在这个特定的模式中,但是如果我将'k'设为静态并改为写这个(在testyn类中):public class testsyn implements Runnable {    static test k = new test( );    public static void main( String[ ] args )    {        new Thread( new testsyn( ) ).start( );        k.inc1( "Main" );    }    public void run( )    {        k.inc1( "Thread" );    }}这将按我预期的方式工作,并且输出之间不会发生冲突。例如,如果主线程首先进入同步方法,那么其他线程将不得不等到主线程完成该方法。我在这里要问的问题是这种变化如何影响程序的行为?为什么?
查看完整描述

2 回答

?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

所以假设我的输出的第一行是:“Main:0”。这意味着主线程已经获取了名为“k”的测试对象的密钥,对吧?我创建的另一个线程怎么可能在主线程完成之前进入“inc1”方法并打印输出?

你写“名为'k'的测试对象”就好像只有一个一样。在您的示例中,k是 class 的实例变量testsyn,因此每个实例都有自己的。它们指的是不同的对象,每个对象都有自己的监视器。因此,执行其中一个对象的同步实例方法的线程不会阻止另一个线程执行另一个对象的同步实例方法。

如果我将'k'设为静态[...],输出之间就不会发生冲突。

是的。 static变量属于声明它们的类。它们由所有实例共享。两个线程共享一个 static k,在运行之前已经初始化main()并且之后没有被修改。由于他们都试图运行同一个对象的同步方法,因此必须等到另一个完成。


查看完整回答
反对 回复 2022-06-04
?
慕的地10843

TA贡献1785条经验 获得超8个赞

是的,synchronized关键字是用来获取锁的;锁与对象实例相关联。你有两个test类的实例;一个给每个线程。所以没有争议。当字段k为静态时,线程之间共享一个实例。



查看完整回答
反对 回复 2022-06-04
  • 2 回答
  • 0 关注
  • 68 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信