NSMutableArray线程安全(NSMutableArray thread safety)

在我的应用程序中,我正在从多个线程访问和更改可变数组。 在开始时,当我尝试访问objectAtIndex对象时发生崩溃,因为索引超出了范围(该索引处的对象已经从另一个线程中的数组中移除)。 我在互联网上搜索如何解决这个问题,我决定尝试这个解决方案 。我做了一个NSMutableArray属性的类,请参阅以下代码:

@interface SynchronizedArray()
@property (retain, atomic) NSMutableArray *array;
@end

@implementation SynchronizedArray

- (id)init
{
    self = [super init];
    if (self)
    {
        _array = [[NSMutableArray alloc] init];
    }
    return self;
}

-(id)objectAtIndex:(NSUInteger)index
{
    @synchronized(_array)
    {
        return [_array objectAtIndex:index];
    }
}

-(void)removeObject:(id)object
{
    @synchronized(_array)
    {
        [_array removeObject:object];
    }
}

-(void)removeObjectAtIndex:(NSUInteger)index
{
    @synchronized(_array)
    {
        [_array removeObjectAtIndex:index];
    }
}

-(void)addObject:(id)object
{
    @synchronized(_array)
    {
        [_array addObject:object];
    }
}

- (NSUInteger)count
{
    @synchronized(_array)
    {
        return [_array count];
    }
}

-(void)removeAllObjects
{
    @synchronized(_array)
    {
        [_array removeAllObjects];
    }
}

-(id)copy
{
    @synchronized(_array)
    {
        return [_array copy];
    }
}

我使用这个类而不是旧的可变数组,但该应用程序仍在这条线上崩溃: return [_array objectAtIndex:index]; 我也试过这种方法与NSLock ,但没有运气。 我做错了什么以及如何解决这个问题?


In my app I'm accessing and changing a mutable array from multiple threads. At the beginning it was crashing when I was trying to access an object with objectAtIndex, because index was out of bounds (object at that index has already been removed from array in another thread). I searched on the internet how to solve this problem, and I decided to try this solution .I made a class with NSMutableArray property, see the following code:

@interface SynchronizedArray()
@property (retain, atomic) NSMutableArray *array;
@end

@implementation SynchronizedArray

- (id)init
{
    self = [super init];
    if (self)
    {
        _array = [[NSMutableArray alloc] init];
    }
    return self;
}

-(id)objectAtIndex:(NSUInteger)index
{
    @synchronized(_array)
    {
        return [_array objectAtIndex:index];
    }
}

-(void)removeObject:(id)object
{
    @synchronized(_array)
    {
        [_array removeObject:object];
    }
}

-(void)removeObjectAtIndex:(NSUInteger)index
{
    @synchronized(_array)
    {
        [_array removeObjectAtIndex:index];
    }
}

-(void)addObject:(id)object
{
    @synchronized(_array)
    {
        [_array addObject:object];
    }
}

- (NSUInteger)count
{
    @synchronized(_array)
    {
        return [_array count];
    }
}

-(void)removeAllObjects
{
    @synchronized(_array)
    {
        [_array removeAllObjects];
    }
}

-(id)copy
{
    @synchronized(_array)
    {
        return [_array copy];
    }
}

and I use this class instead of old mutable array, but the app is still crashing at this line: return [_array objectAtIndex:index]; I tried also this approach with NSLock, but without a luck. What I'm doing wrong and how to fix this?


原文:https://stackoverflow.com/questions/21139581
2023-10-07 19:10

满意答案

你已经快到了。 大概。

您正在使用正确的方法来检索注释,因此您可以使用值。

您的问题 - 如果我解释非常简约的问题描述 (!),您只通过代码片段(!)中的注释正确提供 - 是(错误的)假设将类型Class的数组粘贴到System.out.println中( )将打印出它包含的类的名称。 它不是。 而是打印有关参考的信息:

[Ljava.lang.Class;@15db9742

如果需要类的名称,则必须遍历该数组的元素并使用.getName(),. getSimpleName()或提供Class方法的其他名称之一。

有关如何打印数组元素的更多信息,请访问:

打印Java数组最简单的方法是什么?

当然,如果问题在于您从注释字段中获取空值,那么整个答案可能完全不同于这一点。 但是,由于您没有提供足够的问题描述(“ 无效不是问题描述! ),我们只能猜测您的问题是什么。


The solution for this is making sure the advice method's parameter name match the parameter name in AspectJ expression. In my case, the advice method should look like this:

@Aspect
public class MyAspect {
    @Around("@annotation(myAnnotation)")
    public Object handle(ProceedingJoinPoint joinPoint, MyAnnotation myAnnotation) {
        System.out.println(myAnnotation.exceptionList); // should print out TimeOutException
    }
}

相关问答

更多

IntelliJ IDEA + AspectJ(IntelliJ IDEA + AspectJ)

浪费了更多时间之后,我发现我已经将两种不同的AspectJ sytnax混合在一起。 一个是关于方面(比如“公共方面LoggingAspect”),另一个是常规Java注释(比如“@Aspect”或“@Around”)。 当我用“public class LoggingAspect”替换了“公共方面的LoggingAspect”时,它就起作用了。 很难发现,因为一切仍然没有问题编译。 希望有朝一日能够帮助某人,或者至少在将来的ajc版本中,他们会添加更详细的编译器输出。 After wasting...

使用Spring或AspectJ将基于代码的样式转换为基于注释的样式AOP(Converting Code based style to Annotation Based style AOP using Spring or AspectJ)

不确定您正在阅读哪些文档 - https://eclipse.org/aspectj/doc/next/adk15notebook/ataspectj-pcadvice.html上的页面向您展示了如何从代码转换为注释样式。 我承认他们并不像他们那样全面。 基本上: 从aspect关键字切换到@Aspect 将切入点移动到方法上指定的字符串@Pointcut注释中 将您的建议从未命名的块转换为方法。 (由于要继续的参数,这对于周围的建议可能会变得棘手) 你的原创成为: @Aspect public ...

使用AspectJ Annotation获取方法输入的属性(Get Method Input's Attributes using AspectJ Annotation)

尝试这个: @Around("execution (* *(fully.qualified.name.CloudFile)) && args(cloudFile)") public Object captureFileAttribute(ProceedingJoinPoint joinPoint, CloudFile cloudFile) throws Throwable { Object result = joinPoint.proceed(); System.e...

aspectj切入点匹配特定的注释参数值(aspectj pointcut matching a specific annotation parameter value)

目前,AspectJ支持对允许类型的注释值的子集进行注释值匹配。 不幸的是,不支持您使用的数组类型(也不支持类)。 1.6.0 AspectJ README( https://eclipse.org/aspectj/doc/released/README-160.html )中记录了此功能。 有一个关于'注释值匹配'的部分。 如上所述,语法实际上对于基本情况非常直观: enum TraceLevel { NONE, LEVEL1, LEVEL2, LEVEL3 } @interface Trac...

使用Scala中的aspectj修改方法参数值(Modify a method parameter value using aspectj in Scala)

before()和after()建议不能修改在连接点发生的事情,他们只能观察它。 around()建议会做你需要的。 就像是: void around(long l,boolean b): execution(* delete(..)) && args(l,b) { if ((l%2)==0) { proceed(l,b); } else { proceed(l,!b); } } 对不起,我用代码风格写了它,我对此更熟悉。 这可以使用注释样式,但您需要使用其他变量Pr...

使用AspectJ获取注释参数(Get Annotation Parameter with AspectJ)

你已经快到了。 大概。 您正在使用正确的方法来检索注释,因此您可以使用值。 您的问题 - 如果我解释非常简约的问题描述 (!),您只通过代码片段(!)中的注释正确提供 - 是(错误的)假设将类型Class的数组粘贴到System.out.println中( )将打印出它包含的类的名称。 它不是。 而是打印有关参考的信息: [Ljava.lang.Class;@15db9742 如果需要类的名称,则必须遍历该数组的元素并使用.getName(),. getSimpleName()或提供Class方...

使用AspectJ的Spring / @Transactional完全被忽略(Spring / @Transactional with AspectJ is totally ignored)

尝试添加<context:load-time-weaver/>以启用加载时间编织,并将spring-aspects.jar添加到类路径中。 有关详细信息,请参阅http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-aj-ltw-spring 编辑 对于通用Java应用程序,即不在Web或应用程序容器中运行,您需要通过javaagent选项启用java instr...

AspectJ:如何替换现有注释(AspectJ: How to replace an existing annotation)

我是AspectJ项目的负责人。 在https://bugs.eclipse.org/bugs/show_bug.cgi?id=313026下,我们正在研究如何使用declare annotation: 扩充现有注释(将值添加到已存在的注释中) 替换他们 定义优先级(如果你声明替换那里有什么?) 我们还在寻找一种删除注释的形式: 声明@remove_from_method:int mymethod():@ ToBeRemoved; 但你还不能做到...... I'm the AspectJ pro...

如何将基于注释的转换为本机AspectJ语法(How to convert annotation-based into native AspectJ syntax)

我已经编写了一个关于事务管理评论的MCVE示例,以便使代码及其日志输出更加清晰: 注解: package de.scrum_master.app; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(Ret...

aspectj中注释的优先顺序(precedence order for annotations in aspectj)

使用declare precedence来定义所需的宽高优先顺序。 有关此优先级和默认优先级的更多信息,请参阅“AspectJ编程指南”的“ 语言语义 ”一节。 如果建议顺序应该是动态的,那么最好的办法是让一个切入点同时捕获注释并根据注释的值来决定顺序,这些值可以通过反射来确定。 Use declare precedence in order to define your desired order of aspect precedence. Further information about t...

相关文章

更多

线程报错 thread

/** * 只能这么写 * 不然 腾讯微博会报Can't create handler inside ...

引入thread后socket接受不了报文了

不使用线程thread可以正常接受报文,加了后就在recvfrom那里不动了,是怎么回事? usin ...

关于Thread类中的start()方法和run()方法

引用 public void start() Causes this thread to ...

一步一步掌握java的线程机制(二)----Thread的生命周期

之前讲到Thread的创建,那是Thread生命周期的第一步,其后就是通过start()方法来启动Th ...

关于线程

线程,学了挺久了。我发现我不会写总结这种东西。 好吧,我又词穷了。不知道该怎么写了。先打开eclips ...

action 线程问题。

比如现在有个Action,叫CZaction,有很多用户会访问这个action,这个action有对数 ...

多线程问题

请教各位。本人在尝试写一个银行调度系统。但是多线程上遇到问题。目前有三个并发线程,但是同时只能运行两个 ...

java线程状态详解(6种)

java线程类为:java.lang.Thread,其实现java.lang.Runnable接口。 ...

最新问答

更多

获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)

我用Google搜索了一个解决方案。 “EnumDisplayModeProvider”是我自己设置网站的各种模式的枚举。 public EnumDisplayModeProvider GetDisplayModeId() { foreach (var mode in DisplayModeProvider.Instance.Modes) if (mode.CanHandleContext(HttpContext)) {

如何通过引用返回对象?(How is returning an object by reference possible?)

这相对简单:在类的构造函数中,您可以分配内存,例如使用new 。 如果你制作一个对象的副本,你不是每次都分配新的内存,而是只复制指向原始内存块的指针,同时递增一个也存储在内存中的引用计数器,使得每个副本都是对象可以访问它。 如果引用计数降至零,则销毁对象将减少引用计数并仅释放分配的内存。 您只需要一个自定义复制构造函数和赋值运算符。 这基本上是共享指针的工作方式。 This is relatively easy: In the class' constructor, you allocate m

矩阵如何存储在内存中?(How are matrices stored in memory?)

正如它在“熵编码”中所说的那样,使用Z字形图案,与RLE一起使用,在许多情况下,RLE已经减小了尺寸。 但是,据我所知,DCT本身并没有给出稀疏矩阵。 但它通常会增强矩阵的熵。 这是compressen变得有损的点:输入矩阵用DCT传输,然后量化量化然后使用霍夫曼编码。 As it says in "Entropy coding" a zig-zag pattern is used, together with RLE which will already reduce size for man

每个请求的Java新会话?(Java New Session For Each Request?)

你是如何进行重定向的? 您是否事先调用了HttpServletResponse.encodeRedirectURL()? 在这里阅读javadoc 您可以使用它像response.sendRedirect(response.encodeRedirectURL(path)); The issue was with the path in the JSESSIONID cookie. I still can't figure out why it was being set to the tomca

css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)

我认为word-break ,如果你想在一个单词中打破行,你可以指定它,这样做可以解决问题: .column { word-break:break-all; } jsFiddle演示。 您可以在此处阅读有关word-break属性的更多信息。 I think word-break, with which you can specify if you want to break line within a word, will do the trick: .column { word-break

无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)

我认为您忘记在分类时间内缩放输入图像,如train_test.prototxt文件的第11行所示。 您可能应该在C ++代码中的某个位置乘以该因子,或者使用Caffe图层来缩放输入(请查看ELTWISE或POWER图层)。 编辑: 在评论中进行了一次对话之后,结果发现在classification.cpp文件中错误地删除了图像均值,而在原始训练/测试管道中没有减去图像均值。 I think you have forgotten to scale the input image during cl

xcode语法颜色编码解释?(xcode syntax color coding explained?)

转到: Xcode => Preferences => Fonts & Colors 您将看到每个语法高亮颜色旁边都有一个简短的解释。 Go to: Xcode => Preferences => Fonts & Colors You'll see that each syntax highlighting colour has a brief explanation next to it.

在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)

你考虑过第三方拼写检查吗? 您可以将在C#中开发的自定义WinForms控件插入访问数据库吗? VB6控件怎么样? 如果你能找到一个使用第三方库进行拼写检查的控件,那可能会有效。 Have you considered a third party spell checker? Can you insert a custom WinForms controls developed in C# into an access database? What about a VB6 control? If

从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)

我有同样的问题,因为我在远程服务器上有两个图像,我需要在每天的预定义时间复制到我的本地服务器,这是我能够提出的代码... try { if(@copy('url/to/source/image.ext', 'local/absolute/path/on/server/' . date("d-m-Y") . ".gif")) { } else { $errors = error_get_last(); throw new Exception($err

从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))

我不确定我完全明白你在说什么。 你能编辑你的帖子并包含你正在做的Subversion命令/操作的特定顺序吗? 最好使用命令行svn客户端,以便容易为其他人重现问题。 如果您只是想获取文件的旧副本(即使该文件不再存在),您可以使用如下命令: svn copy ${repo}/trunk/moduleA/file1@${rev} ${repo}/trunk/moduleB/file1 其中${repo}是您的存储库的URL, ${rev}是您想要的文件的版本。 这将恢复该文件的旧版本,包括最高版本