Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 913469
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T17:33:53+00:00 2026-05-15T17:33:53+00:00

I’m puzzling over how multithreading can work with delegates. The main thread has an

  • 0

I’m puzzling over how multithreading can work with delegates.

The main thread has an object “A”, which has created an object “B”. Object “A” is the delegate for object “B”. Object “B” uses a thread to run the code.

When object “B” wants to notify the delegate, it does:

[[self delegate] performSelectorOnMainThread:@selector(didFinish:) withObject:self waitUntilDone:[NSThread isMainThread]];

The “delegate” property is an assign, atomic @property. Hence it would appear that the generated getter will do [[delegate retain] autorelease], according to objective c manual.

The dealloc method for “A” is:

- (void)dealloc
{
    [b setDelegate:nil];
    [b release];
    [super dealloc];
}

This would appear to lead to the possible situation where the threads run like this:

  1. Main thread: call [A dealloc] (due to a call to [a release])
  2. Other thread: b calls [A retain] (due to the call to [self delegate])
  3. Main thread: calls [b setDelegate:nil]
  4. Other thread: calls performSelectorOnMainThread

At step 2, it would seem that retain cannot succeed, as dealloc is already committed to – is this race condition? What happens if you call retain on an object that is in the process of being dealloced? Can it actually occur?

If it is a race condition, how do multi-threaded objects with delegates usually avoid it?

(This arose from a slightly similar but simpler question/answer I previously asked, how to handle setDelegate with multiple threads.)

Update

It is a race conditon, as the accepted answer proves.

The solution to my original problem is to avoid this case all together, I’ve updated How to handle setDelegate: when using multipe threads to show this.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T17:33:54+00:00Added an answer on May 15, 2026 at 5:33 pm

    I don’t think there’s a lock on dealloc versus retain/release. The following example has a dealloc method with a sleep() in it (does anyone know if sleep() breaks locks? I don’t think it does, but you never know). A better example might be to repeatedly instantiate/destroy instances of A and B until you get a situation like the one mentioned here, without the sleep().

    View controller, in my case, but could be anything:

    -(void)septhreadRetainDel
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSLog(@"[thread#2] sleep(1.f);");
        sleep(1.f);
        NSLog(@"[thread#2] [b retainDelegate];");
        [b retainDelegate];
        NSLog(@"[thread#2] sleep(2.f);");
        sleep(2.f);
        NSLog(@"[thread#2] [b release];");
        [b release];
        [pool release];
    }
    
    - (void)viewDidLoad {
        NSLog(@"-(void)viewDidLoad:");
        [super viewDidLoad];
        NSLog(@"a = [[A alloc] init];");
        a = [[A alloc] init];
        NSLog(@"[a autorelease];");
        [a autorelease];
        NSLog(@"b = [[B alloc] init];");
        b = [[B alloc] init];
        NSLog(@"b.delegate = a;");
        b.delegate = a;
        NSLog(@"[NSThread detachNewThreadSelector:@selector(septhreadRetainDel) toTarget:self withObject:nil];");
        [NSThread detachNewThreadSelector:@selector(septhreadRetainDel) toTarget:self withObject:nil];
    }
    

    A:

    #import "A.h"
    
    @implementation A
    
    -(void)dealloc
    {
        NSLog(@"A: dealloc; zzz for 2s");
        sleep(2.f);
        NSLog(@"A: dealloc; waking up in time for my demise!");
        [super dealloc];
    }
    -(id)retain
    {
        NSLog(@"A retain (%d++>%d)", self.retainCount, self.retainCount+1);
        return [super retain];
    }
    -(void)release
    {
        NSLog(@"A release (%d-->%d)", self.retainCount, self.retainCount-1);
        [super release];
    }
    
    @end
    

    B (.h):

    #import "A.h"
    
    @interface B : NSObject {
        A *delegate;
    }
    
    -(void) retainDelegate;
    
    @property (nonatomic, assign) A *delegate;
    
    @end
    

    B (.m):

    #import "B.h"
    
    @implementation B
    
    @synthesize delegate;
    
    -(void)retainDelegate
    {
        NSLog(@"B:: -(void)retainDelegate (delegate currently has %d retain count):", delegate.retainCount);
        NSLog(@"B:: [delegate retain];");
        [delegate retain];
    }
    -(void)releaseDelegate
    {
        NSLog(@"B releases delegate");
        [delegate release];
        delegate = nil;
    }
    
    -(void)dealloc
    {
        NSLog(@"B dealloc; closing shop");
        [self releaseDelegate];
        [super dealloc];
    }
    
    -(id)retain
    {
        NSLog(@"B retain (%d++>%d)", self.retainCount, self.retainCount+1);
        return [super retain];
    }
    -(void)release
    {
        NSLog(@"B release (%d-->%d)", self.retainCount, self.retainCount-1);
        [super release];    
    }
    
    @end
    

    The program ends up crashing with EXC_BAD_ACCESS at B’s releaseDelegate method. The following is the output from the NSLogs:

    2010-07-10 11:49:27.044 race[832:207] -(void)viewDidLoad:
    2010-07-10 11:49:27.050 race[832:207] a = [[A alloc] init];
    2010-07-10 11:49:27.053 race[832:207] [a autorelease];
    2010-07-10 11:49:27.056 race[832:207] b = [[B alloc] init];
    2010-07-10 11:49:27.058 race[832:207] b.delegate = a;
    2010-07-10 11:49:27.061 race[832:207] [NSThread detachNewThreadSelector:@selector(septhreadRetainDel) toTarget:self withObject:nil];
    2010-07-10 11:49:27.064 race[832:4703] [thread#2] sleep(1.f);
    2010-07-10 11:49:27.082 race[832:207] A release (1-->0)
    2010-07-10 11:49:27.089 race[832:207] A: dealloc; zzz for 2s
    2010-07-10 11:49:28.066 race[832:4703] [thread#2] [b retainDelegate];
    2010-07-10 11:49:28.072 race[832:4703] B:: -(void)retainDelegate (delegate currently has 1 retain count):
    2010-07-10 11:49:28.076 race[832:4703] B:: [delegate retain];
    2010-07-10 11:49:28.079 race[832:4703] A retain (1++>2)
    2010-07-10 11:49:28.081 race[832:4703] [thread#2] sleep(2.f);
    2010-07-10 11:49:29.092 race[832:207] A: dealloc; waking up in time for my demise!
    2010-07-10 11:49:30.084 race[832:4703] [thread#2] [b release];
    2010-07-10 11:49:30.089 race[832:4703] B release (1-->0)
    2010-07-10 11:49:30.094 race[832:4703] B dealloc; closing shop
    2010-07-10 11:49:30.097 race[832:4703] B releases delegate
    Program received signal:  “EXC_BAD_ACCESS”.
    

    Once -dealloc is called, retain counts are no longer of import. The object will be destroyed (this is probably obvious, though I wonder what would happen if you checked self’s retainCount and DID NOT call [super dealloc] if the object had retains… insane idea). Now if we modify the -dealloc for A to set B’s delegate to nil first, the program works but only because we’re nil’ing delegate in B in releaseDelegate.

    I don’t know if that answers your question, really, but presuming sleep()’s are not somehow breaking thread locks, the exact same behavior should happen when dealloc is called right before a retain.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm parsing an RSS feed that has an ’ in it. SimpleXML turns this
link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I want to count how many characters a certain string has in PHP, but
I am trying to understand how to use SyndicationItem to display feed which is
I used javascript for loading a picture on my website depending on which small
I have a jquery bug and I've been looking for hours now, I can't
Basically, what I'm trying to create is a page of div tags, each has
I have a string like this: La Torre Eiffel paragonata all’Everest What PHP function
I've got a string that has curly quotes in it. I'd like to replace

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.