Practical Java 书中的错误?

本文通过具体示例探讨了Java中synchronized关键字的使用误区,分析了如何正确地实现对象级锁定来确保线程安全,并提供了测试代码验证结论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《Practical Java》一书“实践51:在单一操作中锁定所有用到的对象”中,有如下代码:

 

public synchronized int sumArrays(int[] a1, int[] a2)
{
  
int value = 0;
  
int size = a1.length;
  
if (size == a2.length)
  {
    
for (int i=0; i<size; i++)
      value 
+= a1[i] + a2[i];
  }
  
return value;
}

然后指出“这段代码的疏漏在于,尽管函数被声明为synchronized,它所操纵的对象却并非如此。记住,关键字synchronized锁定的是对象,而非函数或代码。因此,当另一个线程改变未被锁之对象(内容)时,sumArrays函数依然可以执行。这种情况下会产生错误”,于是,作者提出对付这种错误的办法:

public int sumArrays(int[] a1, int[] a2)
{
  
int value = 0;
  
int size = a1.length;
  
if (size == a2.length)
  {
    
synchronized(a1) {
      
synchronized(a2) {
        
for (int i=0; i<size; i++)
          value 
+= a1[i] + a2[i];
      }
    }
  }
  
return value;
}

并指出,上面的代码,在循环中的数组不可能被其他线程修改。

我认为这个似乎是不对的,其他线程仍然可以修改数组的元素。不知道是我理解错了作者的意图,还是作者错了?

下面是一个测试程序:

 

public class Test
{
    
public static void main(String args[])
    {
        
int a[] = new int[10000];
        Sum s 
= new Sum(a);
        Modify m 
= new Modify(a);
        s.start();
        m.start();
    }
}

class Modify extends Thread
{
    
int a[];
    
    Modify(
int a[])
    {
        
super();
        
this.a = a;    
    }
    
    
public void run()
    {
        
int len = a.length;
        
for(int i=0; i<len; ++i)
        {
            a[i] 
= 1;
        }    
    }
}

class Sum extends Thread
{
    
int a[];
    
    Sum(
int a[])
    {
        
this.a = a;
    }
    
    
void delay()
    {
        
int    x;

        
for(int i=0; i<10++i)
            
for(int j=1; j<100++j)
                x 
= i / j;

    }
    
    
int sum(int a[])
    {
        
int len = a.length;
        
int sum = 0;
        
synchronized(a)
        {
            
for(int i=0; i<len; ++i)
            {
                sum 
+= a[i];
                delay();
            }
        }
        
return sum;
    }
    
    
public void run()
    {
        System.out.println(sum(a));
    }
}

如果按作者说的那样,那么每次运行的时候,打印的值应该是0,事实却并非如此。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值