【问题标题】:synchronized blocks android同步块 android
【发布时间】:2013-07-21 14:27:22
【问题描述】:

我有一个函数:fillFromDB,它从 SQLite DB 填充一个名为 listArrayList 实例。

我还有另一个Thread,应该清除list 并重新填充它。

我的列表有一些问题,因为有时另一个 Thread 会在第一个仍在填充列表时清除列表,从而导致适配器上的 IndexOutOfBoundsException

// This occurs onCreate()
fillFromDb(list);
downloadAndRepopulateList(list);


private void downloadAndRepopulateList(List list) {
    new Thread(new Runnable() {
        @Override public void run() {
            list.clear();
            // Some other clode
        }
    }
}

我知道问题在于它们不是线程安全的,但我之前从未使用过synchronized

所以我的问题是:

如果我像这样更改下载功能:

private void downloadAndRepopulateList(List list) {
    new Thread(new Runnable() {
        @Override public void run() {

            synchronized(list) {

                list.clear();
                // Some other clode
            }
        }
    }
}

它会等待 UIThread 完成填充fillFromDb() 上的列表,然后继续清除并重新填充它吗?

如果没有,我该怎么做?

【问题讨论】:

    标签: android multithreading synchronized


    【解决方案1】:

    虽然我宁愿推荐使用LinkedBlockingQueue。即

      list = new LinkedBlockingQueue<SomeType>();
      fillFromDb(list);
      downloadAndRepopulateList(list);
    
    private void downloadAndRepopulateList(List list) {
    new Thread(new Runnable() {
        @Override public void run() {
             list.clear();
            // Some other clode
        }
    }
    }
    

    LinkedBlockingQueue 自己会为你管理同步,你不需要持有任何锁等。

    如果您希望使用Arraylist 来制作它,则必须从两侧使其成为原子。即要访问list,他们应该首先锁定对象并继续。如果其他人持有锁,则等待。

    synchonized(list){
      fillFromDb(list);
      downloadAndRepopulateList(list);
    }
    
    
    private void downloadAndRepopulateList(List list) {
    new Thread(new Runnable() {
        @Override public void run() {
            synhronized(list){
             list.clear();
             }
            // Some other clode
        }
    }
    }
    

    【讨论】:

    • 所以downloadAndRepopulateList()方法是在一个同步的关键字里面调用的,而且他身上也有一个同步的关键字?
    • 是的。调用synchornized(list) 的线程持有锁对象。在这种情况下,您的其他线程。因此它是必要的
    【解决方案2】:

    要使其正常工作,您还必须在 fillFromDb 方法上进行同步。所以最后你会有两个同步的部分,一个同步你的列表填充,另一个同步清除列表。您也可以将您的列表用作互斥体,但我建议您将单独的对象用作互斥体,就像Object mutex = new Object(); 一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-30
      • 2015-05-25
      • 1970-01-01
      • 1970-01-01
      • 2011-09-18
      • 2011-12-01
      • 1970-01-01
      相关资源
      最近更新 更多